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 | #ifdef __ia64__ |
45 | extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, |
46 | size_t __child_stack_size, int __flags, |
47 | void *__arg, ...); |
48 | char st[256 * 1024] __attribute__ ((aligned)); |
49 | pid_t p = __clone2 (f, st, sizeof (st), TEST_CLONE_FLAGS, 0); |
50 | #else |
51 | char st[128 * 1024] __attribute__ ((aligned)); |
52 | # if _STACK_GROWS_DOWN |
53 | pid_t p = clone (fn: f, child_stack: st + sizeof (st), TEST_CLONE_FLAGS, arg: 0); |
54 | # elif _STACK_GROWS_UP |
55 | pid_t p = clone (f, st, TEST_CLONE_FLAGS, 0); |
56 | # else |
57 | # error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" |
58 | # endif |
59 | #endif |
60 | if (p == -1) |
61 | { |
62 | printf(format: "clone failed: %m\n" ); |
63 | return 1; |
64 | } |
65 | printf (format: "new thread: %d\n" , (int) p); |
66 | |
67 | siginfo_t si; |
68 | do |
69 | if (sigwaitinfo (set: &ss, info: &si) < 0) |
70 | { |
71 | printf(format: "sigwaitinfo failed: %m\n" ); |
72 | kill (pid: p, SIGKILL); |
73 | return 1; |
74 | } |
75 | while (si.si_signo != sig || si.si_code != SI_QUEUE); |
76 | |
77 | int e; |
78 | if (waitpid (pid: p, stat_loc: &e, __WCLONE) != p) |
79 | { |
80 | puts (s: "waitpid failed" ); |
81 | kill (pid: p, SIGKILL); |
82 | return 1; |
83 | } |
84 | if (!WIFEXITED (e)) |
85 | { |
86 | if (WIFSIGNALED (e)) |
87 | printf (format: "died from signal %s\n" , strsignal (WTERMSIG (e))); |
88 | else |
89 | puts (s: "did not terminate correctly" ); |
90 | return 1; |
91 | } |
92 | if (WEXITSTATUS (e) != 0) |
93 | { |
94 | printf (format: "exit code %d\n" , WEXITSTATUS (e)); |
95 | return 1; |
96 | } |
97 | |
98 | if (si.si_int != (int) p) |
99 | { |
100 | printf (format: "expected PID %d, got si_int %d\n" , (int) p, si.si_int); |
101 | kill (pid: p, SIGKILL); |
102 | return 1; |
103 | } |
104 | |
105 | if (si.si_pid != p) |
106 | { |
107 | printf (format: "expected PID %d, got si_pid %d\n" , (int) p, (int) si.si_pid); |
108 | kill (pid: p, SIGKILL); |
109 | return 1; |
110 | } |
111 | |
112 | if (getpid () != mypid) |
113 | { |
114 | puts (s: "my PID changed" ); |
115 | return 1; |
116 | } |
117 | |
118 | return 0; |
119 | } |
120 | |
121 | #define TEST_FUNCTION do_test () |
122 | #include "../test-skeleton.c" |
123 | |