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