1 | /* Tests for posix_spawn signal handling. |
2 | Copyright (C) 2023-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <assert.h> |
20 | #include <getopt.h> |
21 | #include <spawn.h> |
22 | #include <stdlib.h> |
23 | #include <string.h> |
24 | #include <support/check.h> |
25 | #include <support/xsignal.h> |
26 | #include <support/xunistd.h> |
27 | #include <sys/wait.h> |
28 | #include <unistd.h> |
29 | #include <tst-spawn.h> |
30 | |
31 | /* Nonzero if the program gets called via `exec'. */ |
32 | #define CMDLINE_OPTIONS \ |
33 | { "restart", no_argument, &restart, 1 }, |
34 | static int restart; |
35 | |
36 | /* Hold the four initial argument used to respawn the process, plus the extra |
37 | '--direct', '--restart', the check type ('SIG_IGN' or 'SIG_DFL'), and a |
38 | final NULL. */ |
39 | static char *spargs[8]; |
40 | static int check_type_argc; |
41 | |
42 | /* Called on process re-execution. */ |
43 | _Noreturn static void |
44 | handle_restart (int argc, char *argv[]) |
45 | { |
46 | assert (argc == 1); |
47 | |
48 | if (strcmp (argv[0], "SIG_DFL" ) == 0) |
49 | { |
50 | for (int i = 1; i < NSIG; i++) |
51 | { |
52 | struct sigaction sa; |
53 | int r = sigaction (sig: i, NULL, oact: &sa); |
54 | /* Skip internal signals (such as SIGCANCEL). */ |
55 | if (r == -1) |
56 | continue; |
57 | TEST_VERIFY_EXIT (sa.sa_handler == SIG_DFL); |
58 | } |
59 | exit (EXIT_SUCCESS); |
60 | } |
61 | else if (strcmp (argv[0], "SIG_IGN" ) == 0) |
62 | { |
63 | for (int i = 1; i < NSIG; i++) |
64 | { |
65 | struct sigaction sa; |
66 | int r = sigaction (sig: i, NULL, oact: &sa); |
67 | /* Skip internal signals (such as SIGCANCEL). */ |
68 | if (r == -1) |
69 | continue; |
70 | if (i == SIGUSR1 || i == SIGUSR2) |
71 | TEST_VERIFY_EXIT (sa.sa_handler == SIG_IGN); |
72 | else |
73 | TEST_VERIFY_EXIT (sa.sa_handler == SIG_DFL); |
74 | } |
75 | exit (EXIT_SUCCESS); |
76 | } |
77 | |
78 | exit (EXIT_FAILURE); |
79 | } |
80 | |
81 | static void |
82 | spawn_signal_test (const char *type, const posix_spawnattr_t *attr) |
83 | { |
84 | spargs[check_type_argc] = (char*) type; |
85 | |
86 | PID_T_TYPE pid; |
87 | siginfo_t sinfo; |
88 | |
89 | TEST_COMPARE (POSIX_SPAWN (&pid, spargs[0], NULL, attr, spargs, environ), 0); |
90 | TEST_COMPARE (WAITID (P_ALL, 0, &sinfo, WEXITED), 0); |
91 | TEST_COMPARE (sinfo.si_code, CLD_EXITED); |
92 | TEST_COMPARE (sinfo.si_status, 0); |
93 | } |
94 | |
95 | static void |
96 | dummy_sa_handler (int signal) |
97 | { |
98 | } |
99 | |
100 | static void |
101 | do_test_signals (void) |
102 | { |
103 | /* Ensure the initial signal disposition, ignore EINVAL for internal |
104 | signal such as SIGCANCEL. */ |
105 | for (int sig = 1; sig < _NSIG; ++sig) |
106 | sigaction (sig: sig, act: &(struct sigaction) { .sa_handler = SIG_DFL, |
107 | .sa_flags = 0 }, NULL); |
108 | |
109 | { |
110 | /* Check if all signals handler are set to SIG_DFL on spawned process. */ |
111 | spawn_signal_test (type: "SIG_DFL" , NULL); |
112 | } |
113 | |
114 | { |
115 | /* Same as before, but set SIGUSR1 and SIGUSR2 to a handler different than |
116 | SIG_IGN or SIG_DFL. */ |
117 | struct sigaction sa = { 0 }; |
118 | sa.sa_handler = dummy_sa_handler; |
119 | xsigaction (SIGUSR1, newact: &sa, NULL); |
120 | xsigaction (SIGUSR2, newact: &sa, NULL); |
121 | spawn_signal_test (type: "SIG_DFL" , NULL); |
122 | } |
123 | |
124 | { |
125 | /* Check if SIG_IGN is keep as is. */ |
126 | struct sigaction sa = { 0 }; |
127 | sa.sa_handler = SIG_IGN; |
128 | xsigaction (SIGUSR1, newact: &sa, NULL); |
129 | xsigaction (SIGUSR2, newact: &sa, NULL); |
130 | spawn_signal_test (type: "SIG_IGN" , NULL); |
131 | } |
132 | |
133 | { |
134 | /* Check if SIG_IGN handlers are set to SIG_DFL. */ |
135 | posix_spawnattr_t attr; |
136 | posix_spawnattr_init (attr: &attr); |
137 | sigset_t mask; |
138 | sigemptyset (&mask); |
139 | sigaddset (&mask, SIGUSR1); |
140 | sigaddset (&mask, SIGUSR2); |
141 | posix_spawnattr_setsigdefault (attr: &attr, sigdefault: &mask); |
142 | posix_spawnattr_setflags (attr: &attr, POSIX_SPAWN_SETSIGDEF); |
143 | spawn_signal_test (type: "SIG_DFL" , attr: &attr); |
144 | posix_spawnattr_destroy (attr: &attr); |
145 | } |
146 | } |
147 | |
148 | static int |
149 | do_test (int argc, char *argv[]) |
150 | { |
151 | /* We must have either: |
152 | |
153 | - one or four parameters if called initially: |
154 | + argv[1]: path for ld.so optional |
155 | + argv[2]: "--library-path" optional |
156 | + argv[3]: the library path optional |
157 | + argv[4]: the application name |
158 | |
159 | - six parameters left if called through re-execution: |
160 | + argv[1]: the application name |
161 | + argv[2]: check SIG_IGN/SIG_DFL. |
162 | |
163 | * When built with --enable-hardcoded-path-in-tests or issued without |
164 | using the loader directly. */ |
165 | |
166 | if (restart) |
167 | handle_restart (argc: argc - 1, argv: &argv[1]); |
168 | |
169 | TEST_VERIFY_EXIT (argc == 2 || argc == 5); |
170 | |
171 | int i; |
172 | for (i = 0; i < argc - 1; i++) |
173 | spargs[i] = argv[i + 1]; |
174 | spargs[i++] = (char *) "--direct" ; |
175 | spargs[i++] = (char *) "--restart" ; |
176 | check_type_argc = i++; |
177 | spargs[i] = NULL; |
178 | |
179 | |
180 | do_test_signals (); |
181 | |
182 | return 0; |
183 | } |
184 | |
185 | #define TEST_FUNCTION_ARGV do_test |
186 | #include <support/test-driver.c> |
187 | |