1 | #include <sched.h> |
2 | #include <signal.h> |
3 | #include <string.h> |
4 | #include <stdio.h> |
5 | #include <unistd.h> |
6 | #include <sys/types.h> |
7 | #include <sys/wait.h> |
8 | #include <stackinfo.h> |
9 | |
10 | #ifndef TEST_CLONE_FLAGS |
11 | #define TEST_CLONE_FLAGS 0 |
12 | #endif |
13 | |
14 | static int sig; |
15 | |
16 | static int |
17 | f (void *a) |
18 | { |
19 | puts (s: "in f" ); |
20 | union sigval sival; |
21 | sival.sival_int = getpid (); |
22 | printf (format: "pid = %d\n" , sival.sival_int); |
23 | if (sigqueue (pid: getppid (), sig: sig, val: sival) != 0) |
24 | return 1; |
25 | return 0; |
26 | } |
27 | |
28 | |
29 | static int |
30 | do_test (void) |
31 | { |
32 | int mypid = getpid (); |
33 | |
34 | sig = SIGRTMIN; |
35 | sigset_t ss; |
36 | sigemptyset (&ss); |
37 | sigaddset (&ss, sig); |
38 | if (sigprocmask (SIG_BLOCK, set: &ss, NULL) != 0) |
39 | { |
40 | printf (format: "sigprocmask failed: %m\n" ); |
41 | return 1; |
42 | } |
43 | |
44 | char st[128 * 1024] __attribute__ ((aligned)); |
45 | # if _STACK_GROWS_DOWN |
46 | pid_t p = clone (fn: f, child_stack: st + sizeof (st), TEST_CLONE_FLAGS, arg: 0); |
47 | # elif _STACK_GROWS_UP |
48 | pid_t p = clone (f, st, TEST_CLONE_FLAGS, 0); |
49 | # else |
50 | # error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" |
51 | # endif |
52 | if (p == -1) |
53 | { |
54 | printf(format: "clone failed: %m\n" ); |
55 | return 1; |
56 | } |
57 | printf (format: "new thread: %d\n" , (int) p); |
58 | |
59 | siginfo_t si; |
60 | do |
61 | if (sigwaitinfo (set: &ss, info: &si) < 0) |
62 | { |
63 | printf(format: "sigwaitinfo failed: %m\n" ); |
64 | kill (pid: p, SIGKILL); |
65 | return 1; |
66 | } |
67 | while (si.si_signo != sig || si.si_code != SI_QUEUE); |
68 | |
69 | int e; |
70 | if (waitpid (pid: p, stat_loc: &e, __WCLONE) != p) |
71 | { |
72 | puts (s: "waitpid failed" ); |
73 | kill (pid: p, SIGKILL); |
74 | return 1; |
75 | } |
76 | if (!WIFEXITED (e)) |
77 | { |
78 | if (WIFSIGNALED (e)) |
79 | printf (format: "died from signal %s\n" , strsignal (WTERMSIG (e))); |
80 | else |
81 | puts (s: "did not terminate correctly" ); |
82 | return 1; |
83 | } |
84 | if (WEXITSTATUS (e) != 0) |
85 | { |
86 | printf (format: "exit code %d\n" , WEXITSTATUS (e)); |
87 | return 1; |
88 | } |
89 | |
90 | if (si.si_int != (int) p) |
91 | { |
92 | printf (format: "expected PID %d, got si_int %d\n" , (int) p, si.si_int); |
93 | kill (pid: p, SIGKILL); |
94 | return 1; |
95 | } |
96 | |
97 | if (si.si_pid != p) |
98 | { |
99 | printf (format: "expected PID %d, got si_pid %d\n" , (int) p, (int) si.si_pid); |
100 | kill (pid: p, SIGKILL); |
101 | return 1; |
102 | } |
103 | |
104 | if (getpid () != mypid) |
105 | { |
106 | puts (s: "my PID changed" ); |
107 | return 1; |
108 | } |
109 | |
110 | return 0; |
111 | } |
112 | |
113 | #define TEST_FUNCTION do_test () |
114 | #include "../test-skeleton.c" |
115 | |