1 // This tests handling of signals sent from outside the process in the
2 // following combinations: sync and async signals, caught and uncaught
3 // signals, and while blocking or not blocking in a syscall. This exercises
4 // various different paths in Valgrind's signal handling.
5 //
6 // It does this by installing signal handlers for one signal S, spawning
7 // another process P, sending S from P multiple times (all caught), then
8 // sending another signal from P (not caught).
9
10 #include <signal.h>
11 #include <unistd.h>
12 #include <sys/wait.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <time.h>
18
19 static const struct timespec bip = { 0, 1000000000 / 5 }; // 0.2 seconds.
20
handler(int sig)21 static void handler(int sig)
22 {
23 }
24
25 /* Kill our child, but use a separate kill command. This is so that
26 it's running independently of Valgrind, and so is async with
27 respect to thread scheduling. */
do_kill(int pid,int sig)28 static void do_kill(int pid, int sig)
29 {
30 int status;
31 int killer;
32 int ret;
33
34 killer = vfork();
35 if (killer == -1) {
36 perror("killer/vfork");
37 exit(1);
38 }
39
40 // In the child, exec 'kill' in order to send the signal.
41 if (killer == 0) {
42 char sigbuf[20];
43 char pidbuf[20];
44 sprintf(sigbuf, "-%d", sig);
45 sprintf(pidbuf, "%d", pid);
46 execl("/bin/kill", "kill", sigbuf, pidbuf, NULL);
47 perror("exec failed");
48 exit(1);
49 }
50
51 // In the parent, just wait for the child and then check it ran ok.
52 do
53 ret = waitpid(killer, &status, 0);
54 while (ret == -1 && errno == EINTR);
55
56 if (ret != killer) {
57 perror("kill/waitpid");
58 exit(1);
59 }
60
61 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
62 fprintf(stderr, "kill %d failed status=%s %d\n", killer,
63 WIFEXITED(status) ? "exit" : "signal",
64 WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
65 exit(1);
66 }
67 }
68
test(int block,int caughtsig,int fatalsig)69 static void test(int block, int caughtsig, int fatalsig)
70 {
71 int pid;
72 int status;
73 int i;
74
75 fprintf(stderr, "testing: blocking=%d caught=%d fatal=%d... ",
76 block, caughtsig, fatalsig);
77
78 pid = fork();
79 if (pid == -1) {
80 perror("fork");
81 exit(1);
82 }
83
84 // In the child, install the signal handler, then wait for the signal to
85 // arrive:
86 // - if 'block' is set, wait on a system call;
87 // - otherwise, wait in client code (by spinning).
88 // The alarm() calls is so that if something breaks, we don't get stuck.
89 if (pid == 0) {
90 signal(caughtsig, handler);
91 alarm(10);
92
93 for (;;)
94 if (block) {
95 pause();
96 }
97 }
98
99 // In the parent, send the signals.
100 nanosleep(&bip, 0); // Wait for child to get going.
101
102 for (i = 0; i < 5; i++) {
103 do_kill(pid, caughtsig); // Should be caught.
104 nanosleep(&bip, 0);
105 do_kill(pid, caughtsig); // Ditto.
106 do_kill(pid, caughtsig); // Ditto.
107 }
108
109 nanosleep(&bip, 0);
110
111 do_kill(pid, fatalsig); // Should kill it.
112
113 // Check that the child behaved as expected when it received the signals.
114 if (waitpid(pid, &status, 0) != pid) {
115 fprintf(stderr, "FAILED: waitpid failed: %s\n", strerror(errno));
116
117 } else if (!WIFSIGNALED(status) || WTERMSIG(status) != fatalsig) {
118 fprintf(stderr, "FAILED: child exited with unexpected status %s %d\n",
119 WIFEXITED(status) ? "exit" : "signal",
120 WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
121
122 } else {
123 fprintf(stderr, "PASSED\n");
124 }
125 }
126
main()127 int main()
128 {
129 test(/*non-blocked*/0, /* sync*/SIGSEGV, /* sync*/SIGBUS);
130 test(/*non-blocked*/0, /* sync*/SIGSEGV, /*async*/SIGHUP);
131 test(/*non-blocked*/0, /*async*/SIGUSR1, /* sync*/SIGBUS);
132 test(/*non-blocked*/0, /*async*/SIGUSR1, /*async*/SIGHUP);
133 test(/* blocked*/1, /* sync*/SIGSEGV, /* sync*/SIGBUS);
134 test(/* blocked*/1, /* sync*/SIGSEGV, /*async*/SIGHUP);
135 test(/* blocked*/1, /*async*/SIGUSR1, /* sync*/SIGBUS);
136 test(/* blocked*/1, /*async*/SIGUSR1, /*async*/SIGHUP);
137
138 return 0;
139 }
140