Browse Source

Beef up the fork test, checking for proper SIGCHLD behavior

Eric Andersen 22 years ago
parent
commit
2f1259d91c
1 changed files with 45 additions and 13 deletions
  1. 45 13
      test/unistd/fork.c

+ 45 - 13
test/unistd/fork.c

@@ -26,29 +26,61 @@
 #include <unistd.h>
 #include <sys/wait.h>
 
+#define GOT1	(1 << 1)
+#define GOT2	(1 << 2)
+#define GOT3	(1 << 3)
+
+void child_handler(int sig)
+{
+	fprintf(stderr, "I got a SIGCHLD\n");
+}
+
 int main(void) 
 {
-	pid_t pid;
-	int status, wpid;
+	pid_t pid1, pid2, pid3;
+	int status, result, wpid;
+
+	signal(SIGCHLD, child_handler);
 
-	if ((pid = fork()) == 0) {
-		printf("The child process sleeps 5 seconds...\n");
-		sleep(5);
-		printf("Child exiting.\n");
+	if ((pid1 = fork()) == 0) {
+		fprintf(stderr, "The child process sleeps 2 seconds...\n");
+		sleep(4);
+		fprintf(stderr, "Child exiting.\n");
+		exit(-1);
+	}
+	if ((pid2 = fork()) == 0) {
+		fprintf(stderr, "The child process sleeps 3 seconds...\n");
+		sleep(3);
+		fprintf(stderr, "Child exiting.\n");
+		exit(-1);
+	}
+	if ((pid3 = fork()) == 0) {
+		fprintf(stderr, "The child process sleeps 4 seconds...\n");
+		sleep(2);
+		fprintf(stderr, "Child exiting.\n");
 		exit(-1);
 	}
 
-	printf("Parent: waiting for the child to die.\n");
+	fprintf(stderr, "Parent: waiting for the child to die.\n");
+	status = 0;
 	while (1) {
-		wpid = wait(&status);
-		if (wpid > 0 && wpid != pid) {
-			continue;
-		}
-		if (wpid == pid)
+		wpid = waitpid(pid1, &result, WNOHANG);
+		if (wpid == pid1)
+			status |= GOT1;
+
+		wpid = waitpid(pid2, &result, WNOHANG);
+		if (wpid == pid2)
+			status |= GOT2;
+
+		wpid = waitpid(pid3, &result, WNOHANG);
+		if (wpid == pid3)
+			status |= GOT3;
+
+		if (status == (GOT1 | GOT2 | GOT3))
 			break;
 	}
 
-	printf("Child process exited.\nGoodbye.\n");
+	fprintf(stderr, "Child process exited.\nGoodbye.\n");
 	return EXIT_SUCCESS;
 }