Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/tests/lib/libc/stdio Add interrupted I/O tests (from RVP)
details: https://anonhg.NetBSD.org/src/rev/022cda4d35a2
branches: trunk
changeset: 984448:022cda4d35a2
user: christos <christos%NetBSD.org@localhost>
date: Thu Jul 08 09:07:46 2021 +0000
description:
Add interrupted I/O tests (from RVP)
diffstat:
tests/lib/libc/stdio/Makefile | 8 +-
tests/lib/libc/stdio/h_intr.c | 421 +++++++++++++++++++++++++++++++++++
tests/lib/libc/stdio/h_makenumbers.c | 19 +
tests/lib/libc/stdio/h_testnumbers.c | 16 +
tests/lib/libc/stdio/t_intr.sh | 81 ++++++
5 files changed, 544 insertions(+), 1 deletions(-)
diffs (truncated from 576 to 300 lines):
diff -r 5d503cbdc475 -r 022cda4d35a2 tests/lib/libc/stdio/Makefile
--- a/tests/lib/libc/stdio/Makefile Thu Jul 08 09:06:51 2021 +0000
+++ b/tests/lib/libc/stdio/Makefile Thu Jul 08 09:07:46 2021 +0000
@@ -1,5 +1,6 @@
-# $NetBSD: Makefile,v 1.14 2020/06/29 14:22:11 jruoho Exp $
+# $NetBSD: Makefile,v 1.15 2021/07/08 09:07:46 christos Exp $
+NOMAN=
.include <bsd.own.mk>
TESTSDIR= ${TESTSBASE}/lib/libc/stdio
@@ -13,6 +14,11 @@
TESTS_C+= t_popen
TESTS_C+= t_printf
TESTS_C+= t_scanf
+
+TESTS_SH+= t_intr
+
COPTS.t_printf.c += -Wno-format-nonliteral
+PROGS+= h_intr h_makenumbers h_testnumbers
+
.include <bsd.test.mk>
diff -r 5d503cbdc475 -r 022cda4d35a2 tests/lib/libc/stdio/h_intr.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/lib/libc/stdio/h_intr.c Thu Jul 08 09:07:46 2021 +0000
@@ -0,0 +1,421 @@
+/* $NetBSD: h_intr.c,v 1.1 2021/07/08 09:07:46 christos Exp $ */
+
+/**
+ * Test of interrupted writes to popen()'ed commands.
+ *
+ * Example 1:
+ * ./h_fwrite -c "gzip -t" *.gz
+ *
+ * Example 2:
+ * while :; do ./h_fwrite -b $((12*1024)) -t 10 -c "bzip2 -t" *.bz2; sleep 2; done
+ *
+ * Example 3:
+ * Create checksum file:
+ * find /mnt -type f -exec sha512 -n {} + >SHA512
+ *
+ * Check program:
+ * find /mnt -type f -exec ./h_fwrite -b 512 -c run.sh {} +
+ *
+ * ./run.sh:
+ #!/bin/sh
+ set -eu
+ grep -q "^$(sha512 -q)" SHA512
+ *
+ * Author: RVP at sdf.org
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_intr.c,v 1.1 2021/07/08 09:07:46 christos Exp $");
+
+#include <time.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <libgen.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int process(const char *fn);
+ssize_t maxread(FILE *fp, void *buf, size_t size);
+ssize_t smaxread(FILE *fp, void *buf, size_t size);
+ssize_t maxwrite(FILE *fp, const void *buf, size_t size);
+ssize_t smaxwrite(FILE *fp, const void *buf, size_t size);
+static sig_t xsignal(int signo, sig_t handler);
+static void alarmtimer(int wait);
+static void pr_star(int signo);
+static bool isvalid(const char *s);
+static int do_opts(int argc, char* argv[]);
+static void usage(FILE* fp);
+
+/* Globals */
+static struct options {
+ size_t bsize;
+ size_t ssize;
+ int btype;
+ int tmout;
+ const char *cmd;
+} opts;
+
+static const struct {
+ const char *name;
+ int value;
+} btypes[] = {
+ { "IONBF", _IONBF },
+ { "IOLBF", _IOLBF },
+ { "IOFBF", _IOFBF },
+};
+
+enum {
+ MB = 1024 * 1024,
+ BSIZE = 16 * 1024,
+ DEF_MS = 100,
+ MS = 1000,
+};
+
+
+
+int
+main(int argc, char* argv[])
+{
+ int i, rc = EXIT_SUCCESS;
+
+ i = do_opts(argc, argv);
+ argc -= i;
+ argv += i;
+
+ if (argc == 0) {
+ usage(stderr);
+ return rc;
+ }
+
+ xsignal(SIGPIPE, SIG_IGN);
+ for (i = 0; i < argc; i++) {
+ char *s = strdup(argv[i]);
+ printf("%s...", basename(s));
+ fflush(stdout);
+ free(s);
+
+ sig_t osig = xsignal(SIGALRM, pr_star);
+
+ if (process(argv[i]) == 0)
+ printf("ok\n");
+ else
+ rc = EXIT_FAILURE;
+
+ xsignal(SIGALRM, osig);
+ }
+
+ return rc;
+}
+
+static int
+process(const char *fn)
+{
+ FILE *ifp, *ofp;
+ char *buf;
+ size_t nw = 0;
+ int rc = EXIT_FAILURE;
+ ssize_t n;
+
+ if ((buf = malloc(opts.bsize)) == NULL)
+ err(rc, "buffer alloc failed");
+
+ if ((ifp = fopen(fn, "r")) == NULL) {
+ warn("fopen failed: %s", fn);
+ return rc;
+ }
+
+ if ((ofp = popen(opts.cmd, "w")) == NULL)
+ err(rc, "popen failed `%s'", opts.cmd);
+
+ setvbuf(ofp, NULL, opts.btype, opts.ssize);
+ setvbuf(ifp, NULL, opts.btype, opts.ssize);
+
+ alarmtimer(opts.tmout);
+ while ((n = maxread(ifp, buf, opts.bsize)) > 0) {
+ ssize_t i;
+ if ((i = maxwrite(ofp, buf, n)) == -1) {
+ warn("write failed");
+ break;
+ }
+ nw += i;
+ }
+ alarmtimer(0);
+ // printf("%lu\n", nw);
+
+ fclose(ifp);
+ if (pclose(ofp) != 0)
+ warn("command failed `%s'", opts.cmd);
+ else
+ rc = EXIT_SUCCESS;
+
+ return rc;
+}
+
+/**
+ * maxread - syscall version
+ */
+ssize_t
+smaxread(FILE* fp, void* buf, size_t size)
+{
+ char* p = buf;
+ ssize_t nrd = 0;
+ ssize_t n;
+
+ while (size > 0) {
+ n = read(fileno(fp), p, size);
+ if (n < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return -1;
+ } else if (n == 0)
+ break;
+ p += n;
+ nrd += n;
+ size -= n;
+ }
+ return nrd;
+}
+
+/**
+ * maxread - stdio version
+ */
+ssize_t
+maxread(FILE* fp, void* buf, size_t size)
+{
+ char* p = buf;
+ ssize_t nrd = 0;
+ size_t n;
+
+ while (size > 0) {
+ errno = 0;
+ n = fread(p, 1, size, fp);
+ if (n == 0) {
+ printf("ir.");
+ fflush(stdout);
+ if (errno == EINTR)
+ continue;
+ if (feof(fp) || nrd > 0)
+ break;
+ return -1;
+ }
+ if (n != size)
+ clearerr(fp);
+ p += n;
+ nrd += n;
+ size -= n;
+ }
+ return nrd;
+}
+
+/**
+ * maxwrite - syscall version
+ */
+ssize_t
+smaxwrite(FILE* fp, const void* buf, size_t size)
+{
+ const char* p = buf;
+ ssize_t nwr = 0;
+ ssize_t n;
+
+ while (size > 0) {
+ n = write(fileno(fp), p, size);
+ if (n <= 0) {
+ if (errno == EINTR)
+ n = 0;
+ else
+ return -1;
+ }
+ p += n;
+ nwr += n;
+ size -= n;
+ }
+ return nwr;
+}
+
+/**
+ * maxwrite - stdio version (substrate is buggy)
+ */
+ssize_t
+maxwrite(FILE* fp, const void* buf, size_t size)
+{
+ const char* p = buf;
+ ssize_t nwr = 0;
+ size_t n;
+
+ while (size > 0) {
+ errno = 0;
+ n = fwrite(p, 1, size, fp);
+ if (n == 0) {
+ printf("iw.");
+ fflush(stdout);
+ if (errno == EINTR)
+ continue;
+ if (nwr > 0)
+ break;
+ return -1;
+ }
+ if (n != size)
+ clearerr(fp);
+ p += n;
+ nwr += n;
+ size -= n;
+ }
+ return nwr;
+}
+
+/**
+ * wrapper around sigaction() because we want POSIX semantics:
+ * no auto-restarting of interrupted slow syscalls.
Home |
Main Index |
Thread Index |
Old Index