[LTP] [PATCH v3 4/4] Simplify ioctl02.c further

Marius Kittler mkittler@suse.de
Thu Sep 7 17:51:44 CEST 2023


* Use checkpoint API instead of signals
* Use SAFE_…-macros instead of manual error handling

Signed-off-by: Marius Kittler <mkittler@suse.de>
---
 testcases/kernel/syscalls/ioctl/ioctl02.c | 167 ++++++----------------
 1 file changed, 43 insertions(+), 124 deletions(-)

diff --git a/testcases/kernel/syscalls/ioctl/ioctl02.c b/testcases/kernel/syscalls/ioctl/ioctl02.c
index 6b0924c65..30c647ca3 100644
--- a/testcases/kernel/syscalls/ioctl/ioctl02.c
+++ b/testcases/kernel/syscalls/ioctl/ioctl02.c
@@ -13,50 +13,49 @@
  *
  *	In this test, the parent and child open the parentty and the childtty
  *	respectively.  After opening the childtty the child flushes the stream
- *	and sends a SIGUSR1 to the parent (thereby asking it to continue its
- *	testing). The parent, which was waiting for this signal to arrive, now
- *	starts the testing. It issues a TCGETA ioctl to get all the tty
- *	parameters. It then changes them to known values by issuing a TCSETA
- *	ioctl.  Then the parent issues a TCGETA ioctl again and compares the
- *	received values with what it had set earlier. The test fails if TCGETA
- *	or TCSETA fails, or if the received values don't match those that were
- *	set. The parent does all the testing, the requirement of the child
- *	process is to moniter the testing done by the parent, and hence the
- *	child just waits for the parent.
+ *	and sends a wakes the parent (thereby asking it to continue its
+ *	testing). The parent, then starts the testing. It issues a TCGETA
+ *	ioctl to get all the tty parameters. It then changes them to known
+ *	values by issuing a TCSETA ioctl. Then the parent issues a TCGETA
+ *	ioctl again and compares the received values with what it had set
+ *	earlier. The test fails if TCGETA or TCSETA fails, or if the received
+ *	values don't match those that were set. The parent does all the
+ *	testing, the requirement of the child process is to moniter the
+ *	testing done by the parent, and hence the child just waits for the
+ *	parent.
  */
 
 #include <stdio.h>
 #include <fcntl.h>
-#include <signal.h>
 #include <errno.h>
 #include <sys/wait.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <termios.h>
+
+#include "tst_checkpoint.h"
 #include "tst_test.h"
 #include "tst_safe_macros.h"
 
-#define	CNUL	0
-
 static struct termio termio, save_io;
 
 static char *parenttty, *childtty;
 static int parentfd = -1, childfd = -1;
 static int parentpid, childpid;
-static volatile int sigterm, sigusr1, sigusr2;
 
 static int do_child_setup(void);
-static int do_parent_setup(void);
 static int run_ptest(void);
 static int run_ctest(void);
 static int chk_tty_parms();
 static void setup(void);
 static void cleanup(void);
 static void do_child(void);
-static void sigterm_handler(void);
 
 static char *device;
 
+static const int checkpoint_child_ready = 1;
+static const int checkpoint_parent_done_testing = 2;
+
 static void verify_ioctl(void)
 {
 	parenttty = device;
@@ -67,28 +66,21 @@ static void verify_ioctl(void)
 	if (childpid == 0)
 		do_child();
 
-	while (!sigusr1)
-		sleep(1);
+	TST_CHECKPOINT_WAIT(checkpoint_child_ready);
 
-	sigusr1 = 0;
-
-	parentfd = do_parent_setup();
-	if (parentfd < 0) {
-		kill(childpid, SIGTERM);
-		waitpid(childpid, NULL, 0);
-		cleanup();
-	}
+	parentfd = SAFE_OPEN(parenttty, O_RDWR, 0777);
+	/* flush tty queues to remove old output */
+	SAFE_IOCTL(parentfd, TCFLSH, 2);
 
 	/* run the parent test */
 	int rval = run_ptest();
 	if (rval == -1) {
 		/*
 		 * Parent cannot set/get ioctl parameters.
-		 * SIGTERM the child and cleanup.
+		 * wake the child and cleanup.
 		 */
-		kill(childpid, SIGTERM);
+		TST_CHECKPOINT_WAKE(checkpoint_parent_done_testing);
 		waitpid(childpid, NULL, 0);
-		cleanup();
 	}
 
 	if (rval != 0)
@@ -97,17 +89,15 @@ static void verify_ioctl(void)
 	else
 		tst_res(TPASS, "TCGETA/TCSETA tests SUCCEEDED");
 
-	/* FIXME: check return codes. */
-	(void)kill(childpid, SIGTERM);
-	(void)waitpid(childpid, NULL, 0);
+	TST_CHECKPOINT_WAKE(checkpoint_parent_done_testing);
+	waitpid(childpid, NULL, 0);
 
 	/*
 	 * Clean up things from the parent by restoring the
 	 * tty device information that was saved in setup()
 	 * and closing the tty file descriptor.
 	 */
-	if (ioctl(parentfd, TCSETA, &save_io) == -1)
-		tst_res(TINFO, "ioctl restore failed in main");
+	SAFE_IOCTL(parentfd, TCSETA, &save_io);
 	SAFE_CLOSE(parentfd);
 }
 
@@ -151,32 +141,18 @@ static int run_ptest(void)
 	/* Set output modes. */
 	termio.c_oflag = OPOST | OLCUC | ONLCR | ONOCR;
 
-	TEST(ioctl(parentfd, TCSETA, &termio));
+	SAFE_IOCTL(parentfd, TCSETA, &termio);
 
 	/* Get termio and see if all parameters actually got set */
-	int rval = ioctl(parentfd, TCGETA, &termio);
-	if (rval < 0) {
-		tst_res(TFAIL, "ioctl TCGETA failed.  Ending test.");
-		return -1;
-	}
-
+	SAFE_IOCTL(parentfd, TCGETA, &termio);
 	return chk_tty_parms();
 }
 
 static int run_ctest(void)
 {
-	/*
-	 * Wait till the parent has finished testing.
-	 */
-	while (!sigterm)
-		sleep(1);
-
-	sigterm = 0;
-
-	tst_res(TINFO, "child: Got SIGTERM from parent.");
-
-	if (close(childfd) == -1)
-		tst_res(TINFO, "close() in run_ctest() failed");
+	TST_CHECKPOINT_WAIT(checkpoint_parent_done_testing);
+	tst_res(TINFO, "child: parent has finished testing");
+	SAFE_CLOSE(childfd);
 	return 0;
 }
 
@@ -206,12 +182,11 @@ static int chk_tty_parms(void)
 
 	for (i = 0; i < NCC; i++) {
 		if (i == VEOL2) {
-			if (termio.c_cc[VEOL2] == CNUL) {
+			if (!termio.c_cc[VEOL2]) {
 				continue;
 			} else {
 				tst_res(TINFO, "control char %d has "
-					 "incorrect value %d %d", i,
-					 termio.c_cc[i], CNUL);
+					 "incorrect value %d", i, termio.c_cc[i]);
 				flag++;
 				continue;
 			}
@@ -250,110 +225,54 @@ static int chk_tty_parms(void)
 	return flag;
 }
 
-static int do_parent_setup(void)
-{
-	int pfd = SAFE_OPEN(parenttty, O_RDWR, 0777);
-
-	/* flush tty queues to remove old output */
-	SAFE_IOCTL(pfd, TCFLSH, 2);
-	return pfd;
-}
-
 static int do_child_setup(void)
 {
-	int cfd;
-
-	cfd = open(childtty, O_RDWR, 0777);
+	int cfd = SAFE_OPEN(childtty, O_RDWR, 0777);
 	if (cfd < 0) {
-		tst_res(TINFO, "Could not open %s in do_child_setup(), errno "
-			 "= %d", childtty, errno);
-		/* signal the parent so we don't hang the test */
-		kill(parentpid, SIGUSR1);
+		/* wake the parent so we don't hang the test */
+		TST_CHECKPOINT_WAKE(checkpoint_child_ready);
 		return -1;
 	}
 
 	/* flush tty queues to remove old output */
-	if (ioctl(cfd, TCFLSH, 2) < 0) {
-		tst_res(TINFO, "ioctl TCFLSH failed. : errno = %d", errno);
-		/* signal the parent so we don't hang the test */
-		kill(parentpid, SIGUSR1);
+	if (SAFE_IOCTL(cfd, TCFLSH, 2) < 0) {
+		/* wake the parent so we don't hang the test */
+		TST_CHECKPOINT_WAKE(checkpoint_child_ready);
 		return -1;
 	}
 
 	/* tell the parent that we're done */
-	kill(parentpid, SIGUSR1);
+	TST_CHECKPOINT_WAKE(checkpoint_child_ready);
 
 	return cfd;
 }
 
-/*
- * Define the signals handlers here.
- */
-static void sigterm_handler(void)
-{
-	sigterm = 1;
-}
-
-static void sigusr1_handler(void)
-{
-	sigusr1 = 1;
-}
-
-static void sigusr2_handler(void)
-{
-	sigusr2 = 1;
-}
-
 static void setup(void)
 {
 	if (!device)
 		tst_brk(TBROK, "You must specify a tty device with -D option");
 
-	int fd;
-	struct sigaction act;
-
 	/* XXX: TERRNO required all over the place */
-	fd = SAFE_OPEN(device, O_RDWR, 0777);
+	int fd = SAFE_OPEN(device, O_RDWR, 0777);
 
 	/* Save the current device information - to be restored in cleanup() */
 	SAFE_IOCTL(fd, TCGETA, &save_io);
 
 	/* Close the device */
 	SAFE_CLOSE(fd);
-
-	/* Set up the signal handlers */
-	act.sa_handler = (void *)sigterm_handler;
-	act.sa_flags = 0;
-	sigemptyset(&act.sa_mask);
-	(void)sigaction(SIGTERM, &act, 0);
-
-	act.sa_handler = (void *)sigusr1_handler;
-	act.sa_flags = 0;
-	(void)sigaction(SIGUSR1, &act, 0);
-
-	act.sa_handler = (void *)sigusr2_handler;
-	act.sa_flags = 0;
-	(void)sigaction(SIGUSR2, &act, 0);
-
-	act.sa_handler = SIG_IGN;
-	act.sa_flags = 0;
-	(void)sigaction(SIGTTOU, &act, 0);
-
-	sigterm = sigusr1 = sigusr2 = 0;
 }
 
 static void cleanup(void)
 {
-	if (parentfd != -1) {
-		if (ioctl(parentfd, TCSETA, &save_io) == -1)
-			tst_res(TINFO, "ioctl restore failed in cleanup()");
-		if (close(parentfd) == -1)
-			tst_res(TINFO, "close() failed in cleanup()");
+	if (parentfd >= 0) {
+		SAFE_IOCTL(parentfd, TCSETA, &save_io);
+		SAFE_CLOSE(parentfd);
 	}
 }
 
 static struct tst_test test = {
 	.needs_root = 1,
+	.needs_checkpoints = 1,
 	.forks_child = 1,
 	.setup = setup,
 	.cleanup = cleanup,
-- 
2.42.0



More information about the ltp mailing list