----- Original Message -----
> From: "Xiaoguang Wang" <[email protected]>
> To: [email protected]
> Sent: Friday, 25 April, 2014 12:54:07 PM
> Subject: [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default
>
> 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]>
Thanks for tidying up those global variables. I went over code split between
main(), do_parent() and do_child() again and haven't noticed any issues.
I also ran this testcase with various parameters on RHEL6.5 and RHEL7,
all PASSed, ACK.
Regards,
Jan
> ---
> 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
>
------------------------------------------------------------------------------
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