Home | History | Annotate | Download | only in test
      1 #include <stdlib.h>
      2 #include <stddef.h>
      3 #include <unistd.h>
      4 #include <signal.h>
      5 #include <sys/types.h>
      6 #include <sys/socket.h>
      7 #include <stdio.h>
      8 #include <sys/wait.h>
      9 
     10 static const struct sockaddr sa;
     11 
     12 int main(int argc, char *argv[])
     13 {
     14 	int loops;
     15 	int pid;
     16 	sigset_t set;
     17 
     18 	printf(
     19 "Please run me under 'strace -f -oLOG', and examine LOG file for incorrect\n"
     20 "decoding of interrupted syscalls: grep for 'sendto', '??" /* anti-trigraph gap */ "?', 'unavailable'.\n"
     21 "Pass number of iterations in argv[1] (default: 999).\n"
     22 	);
     23 	fflush(NULL);
     24 
     25 	sigemptyset(&set);
     26 	sigaddset(&set, SIGCHLD);
     27 	sigprocmask(SIG_BLOCK, &set, NULL);
     28 
     29 	loops = 999;
     30 	if (argv[1])
     31 		loops = atoi(argv[1]);
     32 
     33 	while (--loops >= 0) {
     34 		pid = fork();
     35 
     36 		if (pid < 0)
     37 			exit(1);
     38 
     39 		if (!pid) {
     40 			/* child */
     41 			int child = getpid();
     42 
     43 			loops = 99;
     44 			while (--loops) {
     45 				pid = fork();
     46 
     47 				if (pid < 0)
     48 					exit(1);
     49 
     50 				if (!pid) {
     51 					/* grandchild: kill child */
     52 					kill(child, SIGKILL);
     53 					exit(0);
     54 				}
     55 
     56 				/* Add various syscalls you want to test here.
     57 				 * strace will decode them and suddenly find
     58 				 * process disappearing.
     59 				 * But leave at least one case "empty", so that
     60 				 * "kill grandchild" happens quicker.
     61 				 * This produces cases when strace can't even
     62 				 * decode syscall number before process dies.
     63 				 */
     64 				switch (loops & 1) {
     65 				case 0:
     66 					break; /* intentionally empty */
     67 				case 1:
     68 					sendto(-1, "Hello cruel world", 17, 0, &sa, sizeof(sa));
     69 					break;
     70 				}
     71 
     72 				/* kill grandchild */
     73 				kill(pid, SIGKILL);
     74 			}
     75 
     76 			exit(0);
     77 		}
     78 
     79 		/* parent */
     80 		wait(NULL);
     81 	}
     82 
     83 	return 0;
     84 }
     85