public inbox for ltp@lists.linux.it
 help / color / mirror / Atom feed
* [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default
@ 2014-04-25 10:54 Xiaoguang Wang
  2014-04-25 14:00 ` Jan Stancek
  2014-04-26 11:27 ` Wanlong Gao
  0 siblings, 2 replies; 3+ messages in thread
From: Xiaoguang Wang @ 2014-04-25 10:54 UTC (permalink / raw)
  To: ltp-list

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 <wangxg.fnst@cn.fujitsu.com>
---
 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
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default
  2014-04-25 10:54 [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default Xiaoguang Wang
@ 2014-04-25 14:00 ` Jan Stancek
  2014-04-26 11:27 ` Wanlong Gao
  1 sibling, 0 replies; 3+ messages in thread
From: Jan Stancek @ 2014-04-25 14:00 UTC (permalink / raw)
  To: Xiaoguang Wang; +Cc: ltp-list





----- Original Message -----
> From: "Xiaoguang Wang" <wangxg.fnst@cn.fujitsu.com>
> To: ltp-list@lists.sourceforge.net
> 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 <wangxg.fnst@cn.fujitsu.com>

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
> Ltp-list@lists.sourceforge.net
> 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
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default
  2014-04-25 10:54 [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default Xiaoguang Wang
  2014-04-25 14:00 ` Jan Stancek
@ 2014-04-26 11:27 ` Wanlong Gao
  1 sibling, 0 replies; 3+ messages in thread
From: Wanlong Gao @ 2014-04-26 11:27 UTC (permalink / raw)
  To: Xiaoguang Wang; +Cc: ltp-list

On 04/25/2014 06:54 PM, Xiaoguang Wang wrote:
> 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 <wangxg.fnst@cn.fujitsu.com>
> ---
>  scenario_groups/default              |   1 +
>  testcases/kernel/ipc/pipeio/pipeio.c | 963 ++++++++++++++++-------------------
>  2 files changed, 441 insertions(+), 523 deletions(-)


Applied, thank you.


Wanlong Gao


------------------------------------------------------------------------------
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
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-04-26 11:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-25 10:54 [LTP] [PATCH v3] pipeio/pipeio.c: cleanup and add it to run default Xiaoguang Wang
2014-04-25 14:00 ` Jan Stancek
2014-04-26 11:27 ` Wanlong Gao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox