Delete some useless comments and fix some. Use SAFE_* macros.
Make a re-arrangement on original code: let parent process work in do_parent(), child process work in do_child(), and arguments parse and initialization work in setup(). Delete several useless or pointless options: Option C: this option is not supported and has no effect to this test. Option B: if this option is specified, the parent process will always return 0, which won't reflect the correct test results. I think it does not make much sense and remove it. Option d: this option is used to specify a directory, where named pipe is created, other than the current directory. Since tst_tmpdir() will create a temporary directory, so I think "-d" option can be removed. printf() is not async-signal-safe, so use write(2) in signal handler directly. Some cleanup. Signed-off-by: Xiaoguang Wang <[email protected]> --- scenario_groups/default | 1 + testcases/kernel/ipc/pipeio/pipeio.c | 963 ++++++++++++++++------------------- 2 files changed, 441 insertions(+), 523 deletions(-) diff --git a/scenario_groups/default b/scenario_groups/default index 196e636..bf7ab79 100644 --- a/scenario_groups/default +++ b/scenario_groups/default @@ -27,3 +27,4 @@ hyperthreading kernel_misc modules fs_ext4 +pipes diff --git a/testcases/kernel/ipc/pipeio/pipeio.c b/testcases/kernel/ipc/pipeio/pipeio.c index 7dfbe44..479d5c8 100644 --- a/testcases/kernel/ipc/pipeio/pipeio.c +++ b/testcases/kernel/ipc/pipeio/pipeio.c @@ -52,28 +52,18 @@ #include "tlibio.h" #include "test.h" +#include "usctest.h" +#include "safe_macros.h" -char *TCID = "pipeio"; /* Test program identifier. */ -int TST_TOTAL = 1; /* Total number of test cases. */ +char *TCID = "pipeio"; +int TST_TOTAL = 1; #define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } } -/* To avoid extensive modifications to the code, use this bodge */ -#define exit(x) myexit(x) -void myexit(int x) -{ - if (x) - tst_resm(TFAIL, "Test failed"); - else - tst_resm(TPASS, "Test passed"); - tst_exit(); -} - #if defined(__linux__) #define NBPW sizeof(int) #endif -#define PPATH "tpipe" #define OCTAL 'o' #define HEX 'x' #define DECIMAL 'd' @@ -90,130 +80,145 @@ void myexit(int x) #define MAX_ERRS 16 #define MAX_EMPTY 256 -void sig_handler(), help(), usage(), prt_buf(), prt_examples(); -void sig_child(); +static int parse_options(int argc, char *argv[]); +static void setup(int argc, char *argv[]); +static void cleanup(void); + +static void do_child(void); +static void do_parent(void); + +static void help(void), usage(void), prt_examples(void); +static void prt_buf(char **addr, char *buf, int length, int format); +static void sig_child(int sig); +static int check_rw_buf(void); + +static volatile sig_atomic_t nchildcompleted; + +/* variables may be modified in setup() */ +static int num_writers = 1; /* number of writers */ +static int num_writes = 1; /* number of writes per child */ +static int loop; /* loop indefinitely */ +static int exit_error = 1; /* exit on error #, zero means no exit */ +static int size = 327; /* default size */ +static int unpipe; /* un-named pipe if non-zero */ +static int verbose; /* verbose mode if set */ +static int quiet; /* quiet mode if set */ +static int num_rpt; /* ping number, how often to print message */ +static int chld_wait; /* max time to wait between writes, 1 == no wait */ +static int parent_wait; /* max time to wait between reads, 1 == no wait */ +static int ndelay = O_NDELAY; /* additional flag to open */ +static char *writebuf; +static char *readbuf; +static char pname[PATH_MAX]; /* contains the name of the named pipe */ +static char *blk_type = NON_BLOCKING_IO; /* blocking i/o or not */ +static char *pipe_type; /* type of pipe under test */ +static int format = HEX; +static int format_size = -1; +static int iotype; /* sync io */ + +/* variables will be modified in running */ +static int error; +static int count; +static int read_fd; +static int write_fd; +static int empty_read; +static int sem_id; + +static union semun { + int val; + struct semid_ds *buf; + unsigned short int *array; +} u; + +int main(int ac, char *av[]) +{ + int i; + unsigned int j; + unsigned int uwait_iter = 1000, uwait_total = 5000000; + pid_t child; -int count = 0; -int Nchildcomplete = 0; + setup(ac, av); -/* - * Ensure PATH_MAX is define - */ -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif /* ! MAXPATHLEN */ -#endif /* PATH_MAX */ - -int main(ac, av) -int ac; -char *av[]; -{ - int i, j, c, error = 0; - int n; - int nb; /* number of bytes read */ - int num_wrters = 1; /* number of writers */ - int num_writes = 1; /* number of writes per child */ - int loop = 0; /* loop indefinitely */ - int exit_error = 1; /* exit on error #, zero means no exit */ - int size = 327; /* default size */ - int unpipe = 0; /* un-named pipe if non-zero */ - int verbose = 0; /* verbose mode if set */ - int quiet = 0; /* quiet mode if set */ - int num_rpt = 0; /* ping number, how often to print message */ - int chld_wait = 0; /* max time to wait between writes, 1 == no wait */ - int parent_wait = 0; /* max time to wait between reads, 1 == no wait */ - int ndelay = O_NDELAY; /* additional flag to open */ - long clock; - char *writebuf = NULL; - char *readbuf = NULL; - double d; - char *cp; - extern char *optarg; - char pname[PATH_MAX]; /* contains the name of the unamed pipe */ - char dir[PATH_MAX]; /* directory to create pipe in */ - char *blk_type; /* blocking i/o or not */ - char *pipe_type; /* type of pipe under test */ - int fds[2]; /* un-named pipe fds */ - int read_fd = 0; - int write_fd = 0; - int empty_read = 0; - time_t start_time, current_time, diff_time; /* start time, current time, diff of times */ - int *count_word; /* holds address where to write writers count */ - int *pid_word; /* holds address where to write writers pid */ - int format; - int format_size = -1; - int background = 0; /* if set, put process in background */ - struct stat stbuf; - int iotype = 0; /* sync io */ - char *toutput; /* for getenv() */ - int sem_id; - struct sembuf sem_op; - union semun { /* for semctl() */ - int val; - struct semid_ds *buf; - unsigned short int *array; - } u; - unsigned int uwait_iter = 1000; - unsigned int uwait_total = 5000000; - - u.val = 0; - format = HEX; - blk_type = NON_BLOCKING_IO; - dir[0] = '\0'; - sprintf(pname, "%s.%d", PPATH, getpid()); - - if ((toutput = getenv("TOUTPUT")) != NULL) { - if (strcmp(toutput, "NOPASS") == 0) { - quiet = 1; + for (i = num_writers; i > 0; --i) { + + child = tst_fork(); + switch (child) { + case -1: + tst_brkm(TBROK | TERRNO, cleanup, "fork() failed"); + case 0: + do_child(); + exit(0); + default: + break; } } - while ((c = - getopt(ac, av, - "T:BbCc:D:d:he:Ef:i:I:ln:p:qs:uvW:w:P:")) != EOF) { + do_parent(); + + if (empty_read) + tst_resm(TWARN, "%d empty reads", empty_read); + + if (error) { + tst_resm(TFAIL, "%d data errors on pipe, read size = %d, %s %s", + error, size, pipe_type, blk_type); + } else if (!quiet) { + tst_resm(TPASS, "%d pipe reads complete, read size = %d, %s %s", + count + 1, size, pipe_type, blk_type); + } + + /* + * wait for all children to finish, timeout after uwait_total + * semtimedop might not be available everywhere + */ + for (j = 0; j < uwait_total; j += uwait_iter) { + if (semctl(sem_id, 1, GETVAL) == 0) + break; + usleep(uwait_iter); + } + + if (j >= uwait_total) { + tst_resm(TWARN, + "Timed out waiting for child processes to exit"); + } + + cleanup(); + tst_exit(); +} + +static int parse_options(int argc, char *argv[]) +{ + char *cp; + int c; + int ret = 0; + static double d; + + while ((c = getopt(argc, argv, "T:bc:D:he:Ef:i:I:ln:p:qs:uvW:w:")) + != -1) { switch (c) { case 'T': TCID = optarg; break; case 'h': help(); - exit(0); - break; - case 'd': /* dir name */ - strcpy(dir, optarg); + ret = 1; break; case 'D': /* pipe name */ strcpy(pname, optarg); break; - case 'B': /* background */ - background = 1; - break; case 'b': /* blocked */ ndelay = 0; blk_type = BLOCKING_IO; break; - case 'C': - fprintf(stderr, - "%s: --C option not supported on this architecture\n", - TCID); - exit(1); - break; case 'c': /* number childern */ - if (sscanf(optarg, "%d", &num_wrters) != 1) { + if (sscanf(optarg, "%d", &num_writers) != 1) { fprintf(stderr, "%s: --c option invalid arg '%s'.\n", TCID, optarg); - usage(); - exit(1); - } else if (num_wrters <= 0) { - fprintf(stderr, - "%s: --c option must be greater than zero.\n", - TCID); - usage(); - exit(1); + ret = 1; + } else if (num_writers <= 0) { + fprintf(stderr, "%s: --c option must be " + "greater than zero.\n", TCID); + ret = 1; } break; case 'e': /* exit on error # */ @@ -221,20 +226,16 @@ char *av[]; fprintf(stderr, "%s: --e option invalid arg '%s'.\n", TCID, optarg); - usage(); - exit(1); + ret = 1; } else if (exit_error < 0) { - fprintf(stderr, - "%s: --e option must be greater than zero.\n", - TCID); - usage(); - exit(1); + fprintf(stderr, "%s: --e option must be " + "greater than zero.\n", TCID); + ret = 1; } break; - case 'E': prt_examples(); - exit(0); + ret = 1; break; case 'f': /* format of buffer on error */ switch (optarg[0]) { @@ -263,32 +264,34 @@ char *av[]; fprintf(stderr, "%s: --f option invalid arg '%s'.\n", TCID, optarg); - fprintf(stderr, - "\tIt must be x(hex), o(octal), d(decimal), a(ascii) or n(none) with opt sz\n"); - exit(1); + fprintf(stderr, "\tIt must be x(hex), o(octal)," + "d(decimal), a(ascii) or n(none) with " + "opt sz\n"); + ret = 1; break; } cp = optarg; cp++; if (*cp) { if (sscanf(cp, "%i", &format_size) != 1) { - fprintf(stderr, - "%s: --f option invalid arg '%s'.\n", - TCID, optarg); - fprintf(stderr, - "\tIt must be x(hex), o(octal), d(decimal), a(ascii) or n(none) with opt sz\n"); - exit(1); + fprintf(stderr, "%s: --f option invalid" + "arg '%s'.\n", TCID, optarg); + fprintf(stderr, "\tIt must be x(hex)," + "o(octal), d(decimal), a(ascii)" + " or n(none) with opt sz\n"); + ret = 1; break; } } break; case 'I': - if ((iotype = lio_parse_io_arg1(optarg)) == -1) { - fprintf(stderr, - "%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n", + iotype = lio_parse_io_arg1(optarg); + if (iotype == -1) { + fprintf(stderr, "%s: --I arg is invalid, " + "must be s, p, f, a, l, L or r.\n", TCID); - exit(1); + ret = 1; } break; @@ -299,42 +302,29 @@ char *av[]; case 'i': case 'n': /* number writes per child */ if (sscanf(optarg, "%d", &num_writes) != 1) { - fprintf(stderr, - "%s: --i/n option invalid arg '%s'.\n", - TCID, optarg); - usage(); - exit(1); + fprintf(stderr, "%s: --i/n option invalid " + "arg '%s'.\n", TCID, optarg); + ret = 1; } else if (num_writes < 0) { - fprintf(stderr, - "%s: --i/n option must be greater than equal to zero.\n", + fprintf(stderr, "%s: --i/n option must be " + "greater than equal to zero.\n", TCID); - usage(); - exit(1); + ret = 1; } if (num_writes == 0) /* loop forever */ ++loop; - - break; - case 'P': /* panic flag */ - fprintf(stderr, - "%s: --P not supported on this architecture\n", - TCID); - exit(1); break; case 'p': /* ping */ if (sscanf(optarg, "%d", &num_rpt) != 1) { fprintf(stderr, "%s: --p option invalid arg '%s'.\n", TCID, optarg); - usage(); - exit(1); + ret = 1; } else if (num_rpt < 0) { - fprintf(stderr, - "%s: --p option must be greater than equal to zero.\n", - TCID); - usage(); - exit(1); + fprintf(stderr, "%s: --p option must be greater" + " than equal to zero.\n", TCID); + ret = 1; } break; case 'q': /* Quiet - NOPASS */ @@ -345,14 +335,11 @@ char *av[]; fprintf(stderr, "%s: --s option invalid arg '%s'.\n", TCID, optarg); - usage(); - exit(1); + ret = 1; } else if (size <= 0) { - fprintf(stderr, - "%s: --s option must be greater than zero.\n", - TCID); - usage(); - exit(1); + fprintf(stderr, "%s: --s option must be greater" + " than zero.\n", TCID); + ret = 1; } break; case 'u': @@ -361,20 +348,17 @@ char *av[]; case 'v': /* verbose */ verbose = 1; break; - case 'W': /* max wait time between writes */ + case 'W': /* max wait time between reads */ d = strtod(optarg, &cp); if (*cp != '\0') { fprintf(stderr, "%s: --w option invalid arg '%s'.\n", TCID, optarg); - usage(); - exit(1); + ret = 1; } else if (d < 0) { - fprintf(stderr, - "%s: --w option must be greater than zero.\n", - TCID); - usage(); - exit(1); + fprintf(stderr, "%s: --w option must be greater" + " than zero.\n", TCID); + ret = 1; } parent_wait = (int)(d * 1000000.0); break; @@ -384,29 +368,59 @@ char *av[]; fprintf(stderr, "%s: --w option invalid arg '%s'.\n", TCID, optarg); - usage(); - exit(1); + ret = 1; } else if (d < 0) { - fprintf(stderr, - "%s: --w option must be greater than zero.\n", - TCID); - usage(); - exit(1); + fprintf(stderr, "%s: --w option must be greater" + " than zero.\n", TCID); + ret = 1; } chld_wait = (int)(d * 1000000.0); break; case '?': - usage(); - exit(1); + ret = 1; break; } + + if (ret == 1) { + usage(); + return ret; + } + } + + return ret; +} + +static void setup(int argc, char *argv[]) +{ + int ret; + char *toutput; + int fds[2]; + + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + tst_tmpdir(); + + if (signal(SIGCHLD, sig_child) == SIG_ERR) { + tst_brkm(TBROK | TERRNO, cleanup, + "set signal handler for SIGCHLD failed"); } + toutput = getenv("TOUTPUT"); + if (toutput != NULL && strcmp(toutput, "NOPASS") == 0) + quiet = 1; + + sprintf(pname, "%s", "tpipe"); + + ret = parse_options(argc, argv); + if (ret == 1) + tst_brkm(TBROK, cleanup, "options parse error"); + if (format_size == -1) format_size = size; /* - * * If there is more than one writer, all writes and reads * must be the same size. Only writes of a size <= PIPE_BUF * are atomic. T @@ -422,376 +436,306 @@ char *av[]; * bytes will be written.) This is the same as: * pipeio -s 4096 -n 13 -c 5 */ - if (size > PIPE_BUF && num_wrters > 1) { + if (size > PIPE_BUF && num_writers > 1) { if (!loop) { - /* we must set num_writes s.t. num_writes*num_wrters doesn't overflow later */ - num_writes = - MIN(((long long)num_writes * size + PIPE_BUF - - 1) / PIPE_BUF, INT_MAX / num_wrters); - tst_resm(TINFO, - "adjusting i/o size to %d, and # of writes to %d", - PIPE_BUF, num_writes); + /* + * we must set num_writes*num_writers + * doesn't overflow later + */ + num_writes = MIN(((long long)num_writes * size + + PIPE_BUF - 1) / PIPE_BUF, + INT_MAX / num_writers); + tst_resm(TINFO, "adjusting i/o size to %d, and # of " + "writes to %d", PIPE_BUF, num_writes); } else { tst_resm(TINFO, "adjusting i/o size to %d", PIPE_BUF); } size = PIPE_BUF; - } - if ((writebuf = (char *)malloc(size)) == NULL || - (readbuf = (char *)malloc(size)) == NULL) { - tst_resm(TFAIL | TERRNO, "malloc() failed"); - SAFE_FREE(writebuf); - SAFE_FREE(readbuf); - exit(1); - } + writebuf = SAFE_MALLOC(cleanup, size); + readbuf = SAFE_MALLOC(cleanup, size); memset(writebuf, 'Z', size); + writebuf[size - 1] = 'A'; - writebuf[size - 1] = 'A'; /* to detect partial read/write problem */ - - if ((sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU)) == -1) { - tst_brkm(TBROK | TERRNO, NULL, "Couldn't allocate semaphore"); + sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU); + if (sem_id == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "Couldn't allocate semaphore"); } - if (semctl(sem_id, 0, SETVAL, u) == -1) - tst_brkm(TBROK | TERRNO, NULL, + if (semctl(sem_id, 0, SETVAL, u) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, "Couldn't initialize semaphore 0 value"); + } - /* semaphore to hold off children from exiting until open() completes */ - if (semctl(sem_id, 1, SETVAL, u) == -1) - tst_brkm(TBROK | TERRNO, NULL, + if (semctl(sem_id, 1, SETVAL, u) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, "Couldn't initialize semaphore 1 value"); - - if (background) { - if ((n = fork()) == -1) { - tst_resm(TFAIL | TERRNO, "fork() failed"); - exit(1); - } else if (n != 0) /* parent */ - exit(0); } if (unpipe) { - if (pipe(fds) == -1) { - tst_resm(TFAIL | TERRNO, - "pipe() failed to create un-named pipe"); - exit(1); - } + SAFE_PIPE(cleanup, fds); read_fd = fds[0]; write_fd = fds[1]; pipe_type = PIPE_UNNAMED; blk_type = UNNAMED_IO; } else { - if (strlen(dir) && chdir(dir) == -1) { - tst_resm(TFAIL | TERRNO, "chdir(%s) failed", dir); - exit(1); - } - - if (stat(pname, &stbuf) == -1) { - - if (mkfifo(pname, 0777) == -1) { - tst_resm(TFAIL | TERRNO, - "mkfifo(%s,0777) failed", pname); - exit(1); - } + if (mkfifo(pname, 0777) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "mkfifo(%s, 0777) failed", pname); } pipe_type = PIPE_NAMED; } +} - start_time = time(0); +static void cleanup(void) +{ + TEST_CLEANUP; -#if DEBUG - printf("num_wrters = %d\n", num_wrters); -#endif + SAFE_FREE(writebuf); + SAFE_FREE(readbuf); + + semctl(sem_id, 0, IPC_RMID); + + if (!unpipe) + SAFE_UNLINK(NULL, pname); + + tst_rmdir(); +} + +static void do_child(void) +{ + int *count_word; /* holds address where to write writers count */ + int *pid_word; /* holds address where to write writers pid */ + int nb, j; + long clock; + char *cp; + long int n; + struct sembuf sem_op; + pid_t self_pid = getpid(); -#ifdef linux - signal(SIGCHLD, sig_child); - signal(SIGHUP, sig_handler); - signal(SIGINT, sig_handler); - signal(SIGQUIT, sig_handler); -#ifdef SIGRECOVERY - signal(SIGRECOVERY, sig_handler); -#endif /* SIGRECOVERY */ -#else - sigset(SIGCHLD, sig_child); - sigset(SIGHUP, sig_handler); - sigset(SIGINT, sig_handler); - sigset(SIGQUIT, sig_handler); -#ifdef SIGRECOVERY - sigset(SIGRECOVERY, sig_handler); -#endif /* SIGRECOVERY */ -#endif /* linux */ - - for (i = num_wrters; i > 0; --i) { - if ((c = fork()) < 0) { - tst_resm(TFAIL | TERRNO, "fork() failed"); + if (!unpipe) { + write_fd = open(pname, O_WRONLY); + if (write_fd == -1) { + fprintf(stderr, "child pipe open(%s, %#o) failed", + pname, O_WRONLY | ndelay); exit(1); } - if (c == 0) - break; /* stop child from forking */ - } - if (c == 0) { /***** if child *****/ -#if DEBUG - printf("child after fork pid = %d\n", getpid()); -#endif - if (!unpipe) { - if ((write_fd = open(pname, O_WRONLY)) == -1) { - tst_resm(TFAIL | TERRNO, - "child pipe open(%s, %#o) failed", - pname, O_WRONLY | ndelay); - exit(1); - } - if (ndelay - && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) { - tst_brkm(TBROK | TERRNO, NULL, - "Failed setting the pipe to nonblocking mode"); - } - } else { - close(read_fd); + if (ndelay && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) { + fprintf(stderr, "Failed setting the pipe to " + "nonblocking mode"); + exit(1); } + } else { + close(read_fd); + } - sem_op = (struct sembuf) { - .sem_num = 0,.sem_op = 1,.sem_flg = 0}; + sem_op = (struct sembuf) { + .sem_num = 0, .sem_op = 1, .sem_flg = 0}; - if (semop(sem_id, &sem_op, 1) == -1) - tst_brkm(TBROK | TERRNO, NULL, - "Couldn't raise the semaphore 0"); + if (semop(sem_id, &sem_op, 1) == -1) { + fprintf(stderr, "child: %d couldn't raise the semaphore 0", + self_pid); + exit(1); + } - pid_word = (int *)&writebuf[0]; - count_word = (int *)&writebuf[NBPW]; + pid_word = (int *)&writebuf[0]; + count_word = (int *)&writebuf[NBPW]; - for (j = 0; j < num_writes || loop; ++j) { + for (j = 0; j < num_writes || loop; ++j) { + /* + * writes are only in one unit when the size of the write + * is <= PIPE_BUF. + * Therefore, if size is greater than PIPE_BUF, we will break + * the writes into PIPE_BUF chunks. + * All writes and read need to be same size. + */ - /* writes are only in one unit when the size of the write - * is <= PIPE_BUF. - * Therefore, if size is greater than PIPE_BUF, we will break - * the writes into PIPE_BUF chunks. - * All writes and read need to be same size. - */ + /* + * write pid and count in first two + * words of buffer + */ + *count_word = j; + *pid_word = self_pid; + nb = lio_write_buffer(write_fd, iotype, writebuf, size, + SIGUSR1, &cp, 0); + if (nb < 0) { /* - * write pid and count in first two - * words of buffer + * If lio_write_buffer returns a negative number, + * the return will be -errno. */ - - *count_word = j; - *pid_word = getpid(); - - if ((nb = - lio_write_buffer(write_fd, iotype, writebuf, size, - SIGUSR1, &cp, 0)) < 0) { - /* - * If lio_write_buffer returns a negative number, - * the return will be -errno. - */ - tst_resm(TFAIL, - "pass %d: lio_write_buffer(%s) failed; it returned %d: %s", - j, cp, nb, strerror(-nb)); + fprintf(stderr, "pass %d: lio_write_buffer(%s) failed;" + " it returned %d: %s", + j, cp, nb, strerror(-nb)); exit(1); - } else if (nb != size) { - tst_resm(TFAIL, - "pass %d: lio_write_buffer(%s) failed, write count %d, but expected to write %d", - j, cp, nb, size); - } - if (verbose) - tst_resm(TINFO, - "pass %d: pid %d: wrote %d bytes, expected %d bytes", - j, getpid(), nb, size); - - if (chld_wait) { - clock = time(0); - srand48(clock); - n = lrand48() % chld_wait; - usleep(n); - } - fflush(stderr); + } else if (nb != size) { + fprintf(stderr, "pass %d: lio_write_buffer(%s) failed," + " write count %d, but expected to write %d", + j, cp, nb, size); + } + if (verbose) { + fprintf(stderr, "pass %d: pid %d: wrote %d bytes," + "expected %d bytes", + j, self_pid, nb, size); } - /* child waits until parent completes open() */ - sem_op = (struct sembuf) { - .sem_num = 1,.sem_op = -1,.sem_flg = 0}; - if (semop(sem_id, &sem_op, 1) == -1) - tst_brkm(TBROK | TERRNO, NULL, - "Couldn't lower the semaphore 1"); + if (chld_wait) { + clock = time(0); + srand48(clock); + n = lrand48() % chld_wait; + usleep(n); + } + fflush(stderr); } - if (c > 0) { /***** if parent *****/ - if (!unpipe) { - if ((read_fd = open(pname, O_RDONLY)) == -1) { - tst_resm(TFAIL | TERRNO, - "parent pipe open(%s, %#o) failed", - pname, O_RDONLY); - exit(1); - } - if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) { - tst_brkm(TBROK | TERRNO, NULL, - "Failed setting the pipe to nonblocking mode"); - } - } else { - close(write_fd); + /* child waits until parent completes open() */ + sem_op = (struct sembuf) { + .sem_num = 1, .sem_op = -1, .sem_flg = 0}; + if (semop(sem_id, &sem_op, 1) == -1) + fprintf(stderr, "Couldn't lower the semaphore 1"); + + exit(0); +} + +static int check_rw_buf(void) +{ + int i; + + for (i = 2 * NBPW; i < size; ++i) { + if (writebuf[i] != readbuf[i]) { + ++error; + tst_resm(TFAIL, + "FAIL data error on byte %d; rd# %d, sz= %d, " + "%s %s empty_reads= %d, err= %d", + i, count, size, pipe_type, blk_type, + empty_read, error); + prt_buf(&readbuf, readbuf, format_size, format); + fflush(stdout); + return 1; } + } - /* raise semaphore so children can exit */ - sem_op = (struct sembuf) { - .sem_num = 1,.sem_op = num_wrters,.sem_flg = 0}; - if (semop(sem_id, &sem_op, 1) == -1) - tst_brkm(TBROK | TERRNO, NULL, - "Couldn't raise the semaphore 1"); + return 0; +} - sem_op = (struct sembuf) { - .sem_num = 0,.sem_op = -num_wrters,.sem_flg = 0}; +static void do_parent(void) +{ + int i, nb; + long clock; + time_t start_time, current_time, diff_time; + char *cp; + long int n; + struct sembuf sem_op; - while (Nchildcomplete < num_wrters - && semop(sem_id, &sem_op, 1) == -1) { - if (errno == EINTR) { - continue; - } - tst_brkm(TBROK | TERRNO, NULL, - "Couldn't wait on semaphore 0"); + start_time = time(0); + if (!unpipe) { + read_fd = SAFE_OPEN(cleanup, pname, O_RDONLY); + if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "Failed setting the pipe to nonblocking mode"); } + } else { + SAFE_CLOSE(cleanup, write_fd); + } - for (i = num_wrters * num_writes; i > 0 || loop; --i) { - if (error >= MAX_ERRS || empty_read >= MAX_EMPTY) - break; - if (parent_wait) { - clock = time(0); - srand48(clock); - n = lrand48() % parent_wait; - usleep(n); - } - ++count; - if ((nb = - lio_read_buffer(read_fd, iotype, readbuf, size, - SIGUSR1, &cp, 0)) < 0) { - /* - * If lio_read_buffer returns a negative number, - * the return will be -errno. - */ - tst_resm(TFAIL, - "pass %d: lio_read_buffer(%s) failed; it returned %d: %s", - i, cp, nb, strerror(-nb)); + /* raise semaphore so children can exit */ + sem_op = (struct sembuf) { + .sem_num = 1, .sem_op = num_writers, .sem_flg = 0}; + if (semop(sem_id, &sem_op, 1) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "Couldn't raise the semaphore 1"); + } + + sem_op = (struct sembuf) { + .sem_num = 0, .sem_op = -num_writers, .sem_flg = 0}; + + while (nchildcompleted < num_writers + && semop(sem_id, &sem_op, 1) == -1) { + if (errno == EINTR) + continue; + tst_brkm(TBROK | TERRNO, cleanup, + "Couldn't wait on semaphore 0"); + } + + /* parent start to read pipe */ + for (i = num_writers * num_writes; i > 0 || loop; --i) { + if (error >= MAX_ERRS || empty_read >= MAX_EMPTY) + break; + if (parent_wait) { + clock = time(0); + srand48(clock); + n = lrand48() % parent_wait; + usleep(n); + } + ++count; + nb = lio_read_buffer(read_fd, iotype, readbuf, size, + SIGUSR1, &cp, 0); + if (nb < 0) { + /* + * If lio_read_buffer returns a negative number, + * the return will be -errno. + */ + tst_resm(TFAIL, "pass %d: lio_read_buffer(%s) failed; " + "returned %d: %s", i, cp, nb, strerror(-nb)); + ++i; + count--; + error++; + continue; + } else { + if (nb == 0) { + if (nchildcompleted >= num_writers && !loop) { + tst_resm(TWARN, "The children have " + "died prematurely"); + break; /* All children have died */ + } + empty_read++; ++i; count--; - error++; continue; - - } else { - if (nb == 0) { - if (Nchildcomplete >= num_wrters) { - if (!loop) - tst_resm(TWARN, - "The children have died prematurely"); - break; /* All children have died */ - } - empty_read++; -/* - fprintf(stdout, - "%s: Nothing on the pipe (%d),read count %d (read not counted)\n", - TCID,empty_read,count); - fflush(stdout); - */ - ++i; - count--; - continue; - } else if (nb < size && size <= PIPE_BUF) { - tst_resm(TFAIL, - "pass %d: partial read from the pipe: read %d bytes, expected %d, read count %d", - i, nb, size, count); - ++error; - } else if (nb == size) { - for (j = 2 * NBPW; j < size; ++j) { - if (writebuf[j] != readbuf[j]) { - ++error; - tst_resm(TFAIL, - "1 FAIL data error on byte %d; rd# %d, sz= %d, %s %s empty_reads= %d, err= %d", - j, count, size, - pipe_type, - blk_type, - empty_read, - error); - prt_buf(&readbuf, - readbuf, - format_size, - format); - fflush(stdout); - if (exit_error - && exit_error == - error) - goto output; - - else - break; - } - } - } - if (verbose || (num_rpt && !(count % num_rpt))) { - current_time = time(0); - diff_time = current_time - start_time; /* elapsed time */ - tst_resm(TFAIL, - "(%d) rd# %d, sz= %d, %s %s empty_reads= %d, err= %d\n", - (int)diff_time, count, size, - pipe_type, blk_type, - empty_read, error); - fflush(stdout); - } + } else if (nb < size && size <= PIPE_BUF) { + tst_resm(TFAIL, "pass %d: partial read from the" + " pipe: read %d bytes, expected %d, " + "read count %d", i, nb, size, count); + ++error; + } else if (nb == size) { + check_rw_buf(); + if (exit_error && exit_error == error) + return; } - } - if (empty_read) - tst_resm(TWARN, "%d empty reads", empty_read); -output: - if (error) - tst_resm(TFAIL, - "1 FAIL %d data errors on pipe, read size = %d, %s %s", - error, size, pipe_type, blk_type); - else if (!quiet) - tst_resm(TPASS, - "1 PASS %d pipe reads complete, read size = %d, %s %s", - count + 1, size, pipe_type, blk_type); - - /* wait for all children to finish, timeout after uwait_total - semtimedop might not be available everywhere */ - for (i = 0; i < uwait_total; i += uwait_iter) { - if (semctl(sem_id, 1, GETVAL) == 0) { - break; - } - usleep(uwait_iter); - } - if (i > uwait_total) { - tst_resm(TWARN, - "Timed out waiting for child processes to exit"); + if (verbose || (num_rpt && !(count % num_rpt))) { + current_time = time(0); + diff_time = current_time - start_time; + tst_resm(TFAIL, + "(%d) rd# %d, sz= %d, %s %s " + "empty_reads= %d, err= %d\n", + (int)diff_time, count, size, + pipe_type, blk_type, + empty_read, error); + fflush(stdout); + } } - - semctl(sem_id, 0, IPC_RMID); - - if (!unpipe) - unlink(pname); } - - SAFE_FREE(writebuf); - SAFE_FREE(readbuf); - return (error); } -void usage() +static void usage(void) { - fprintf(stderr, - "Usage: %s [-BbCEv][-c #writers][-D pname][-d dir][-h][-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]\n\t[-s size][-W max_wait][-w max_wait][-u]\n", - TCID); + fprintf(stderr, "Usage: %s [-bEv][-c #writers][-D pname][-h]" + "[-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]" + "\n\t[-s size][-W max_wait][-w max_wait][-u]\n", TCID); fflush(stderr); - } -void help() +static void help(void) { usage(); - printf(" -B - execute actions in background\n\ - -b - blocking reads and writes. default non-block\n\ + printf(" -b - blocking reads and writes. default non-block\n\ -c #writers - number of writers (childern)\n\ -D pname - name of fifo (def tpipe<pid>)\n\ - -d dir - cd to dir before creating named pipe\n\ - - (silently ignored if used with -u)\n\ -h - print this help message\n\ -e exit_num - exit on error exit_num, 0 is ignore errors, 1 is default.\n\ -E - print cmd line examples and exit\n\ @@ -815,12 +759,10 @@ void help() -v - verbose mode, all writes/reads resutlts printed\n"); fflush(stdout); - } -void prt_buf(long addr, char *buf, int length, int format) +static void prt_buf(char **addr, char *buf, int length, int format) { - int i; int num_words = length / NBPW; /* given length in bytes, get length in words */ int width; /* number of columns */ @@ -856,13 +798,13 @@ void prt_buf(long addr, char *buf, int length, int format) * get the last 2 words printed */ memcpy(c, a - (width * NBPW), width * NBPW); - for (p = c; (p - c) < width * NBPW; ++p) { + for (p = c; (p - c) < (int)(width*NBPW); ++p) { if (*p < '!' || *p > '~') *p = '.'; } printf("\t%16.16s", c); } - printf("\n%7lo: ", addr); + printf("\n%p: ", addr); /***printf("\n%7o (%d): ",addr,i);***/ } @@ -875,7 +817,7 @@ void prt_buf(long addr, char *buf, int length, int format) break; case ASCII: memcpy(b, a, NBPW); - for (p = b; (p - b) < NBPW; ++p) { + for (p = b; (p - b) < (int)NBPW; ++p) { if (*p < '!' || *p > '~') *p = '.'; } @@ -895,7 +837,7 @@ void prt_buf(long addr, char *buf, int length, int format) if (extra_words) width = extra_words; /* odd number of words */ memcpy(c, a - (width * NBPW), width * NBPW); - for (p = c; (p - c) < width * NBPW; ++p) { + for (p = c; (p - c) < (int)(width * NBPW); ++p) { if (*p < '!' || *p > '~') *p = '.'; } @@ -908,46 +850,21 @@ void prt_buf(long addr, char *buf, int length, int format) fflush(stdout); } -void prt_examples() +static void prt_examples(void) { printf("%s -c 5 -i 0 -s 4090 -b\n", TCID); printf("%s -c 5 -i 0 -s 4090 -b -u \n", TCID); printf("%s -c 5 -i 0 -s 4090 -b -W 3 -w 3 \n", TCID); - } -void sig_child(int sig) +static void sig_child(int sig) { int status; - Nchildcomplete++; + nchildcompleted++; #if DEBUG - printf("parent: received SIGCHLD\n"); + #define STR "parent: received SIGCHLD\n" + write(STDOUT_FILENO, str, strlen(STR)); #endif waitpid(-1, &status, WNOHANG); -#if linux - signal(SIGCHLD, sig_child); -#else - sigset(SIGCHLD, sig_child); -#endif -} - -void sig_handler(int sig) -{ -#ifdef SIGRECOVERY - if (sig == SIGRECOVERY) { - printf("%s: received SIGRECOVERY, count = %d\n", TCID, count); - fflush(stdout); -#ifdef linux - signal(sig, sig_handler); -#else - sigset(sig, sig_handler); -#endif - return; - } -#endif - printf("%s: received unexpected signal: %d\n", TCID, sig); - fflush(stdout); - exit(3); - } -- 1.8.2.1 ------------------------------------------------------------------------------ Start Your Social Network Today - Download eXo Platform Build your Enterprise Intranet with eXo Platform Software Java Based Open Source Intranet - Social, Extensible, Cloud Ready Get Started Now And Turn Your Intranet Into A Collaboration Platform http://p.sf.net/sfu/ExoPlatform _______________________________________________ Ltp-list mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ltp-list
