posix: Ensure the initial signal disposition for tst-spawn7
[glibc.git] / posix / tst-spawn7.c
blobfb06915cb7e6387b6c1f41aad102527c0eb19c39
1 /* Tests for posix_spawn signal handling.
2 Copyright (C) 2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
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 <unistd.h>
29 /* Nonzero if the program gets called via `exec'. */
30 #define CMDLINE_OPTIONS \
31 { "restart", no_argument, &restart, 1 },
32 static int restart;
34 /* Hold the four initial argument used to respawn the process, plus the extra
35 '--direct', '--restart', the check type ('SIG_IGN' or 'SIG_DFL'), and a
36 final NULL. */
37 static char *spargs[8];
38 static int check_type_argc;
40 /* Called on process re-execution. */
41 _Noreturn static void
42 handle_restart (int argc, char *argv[])
44 assert (argc == 1);
46 if (strcmp (argv[0], "SIG_DFL") == 0)
48 for (int i = 1; i < NSIG; i++)
50 struct sigaction sa;
51 int r = sigaction (i, NULL, &sa);
52 /* Skip internal signals (such as SIGCANCEL). */
53 if (r == -1)
54 continue;
55 TEST_VERIFY_EXIT (sa.sa_handler == SIG_DFL);
57 exit (EXIT_SUCCESS);
59 else if (strcmp (argv[0], "SIG_IGN") == 0)
61 for (int i = 1; i < NSIG; i++)
63 struct sigaction sa;
64 int r = sigaction (i, NULL, &sa);
65 /* Skip internal signals (such as SIGCANCEL). */
66 if (r == -1)
67 continue;
68 if (i == SIGUSR1 || i == SIGUSR2)
69 TEST_VERIFY_EXIT (sa.sa_handler == SIG_IGN);
70 else
71 TEST_VERIFY_EXIT (sa.sa_handler == SIG_DFL);
73 exit (EXIT_SUCCESS);
76 exit (EXIT_FAILURE);
79 static void
80 spawn_signal_test (const char *type, const posix_spawnattr_t *attr)
82 spargs[check_type_argc] = (char*) type;
84 pid_t pid;
85 int status;
87 TEST_COMPARE (posix_spawn (&pid, spargs[0], NULL, attr, spargs, environ), 0);
88 TEST_COMPARE (xwaitpid (pid, &status, 0), pid);
89 TEST_VERIFY (WIFEXITED (status));
90 TEST_VERIFY (!WIFSIGNALED (status));
91 TEST_COMPARE (WEXITSTATUS (status), 0);
94 static void
95 dummy_sa_handler (int signal)
99 static void
100 do_test_signals (void)
102 /* Ensure the initial signal disposition, ignore EINVAL for internal
103 signal such as SIGCANCEL. */
104 for (int sig = 1; sig < _NSIG; ++sig)
105 sigaction (sig, &(struct sigaction) { .sa_handler = SIG_DFL,
106 .sa_flags = 0 }, NULL);
109 /* Check if all signals handler are set to SIG_DFL on spawned process. */
110 spawn_signal_test ("SIG_DFL", NULL);
114 /* Same as before, but set SIGUSR1 and SIGUSR2 to a handler different than
115 SIG_IGN or SIG_DFL. */
116 struct sigaction sa = { 0 };
117 sa.sa_handler = dummy_sa_handler;
118 xsigaction (SIGUSR1, &sa, NULL);
119 xsigaction (SIGUSR2, &sa, NULL);
120 spawn_signal_test ("SIG_DFL", NULL);
124 /* Check if SIG_IGN is keep as is. */
125 struct sigaction sa = { 0 };
126 sa.sa_handler = SIG_IGN;
127 xsigaction (SIGUSR1, &sa, NULL);
128 xsigaction (SIGUSR2, &sa, NULL);
129 spawn_signal_test ("SIG_IGN", NULL);
133 /* Check if SIG_IGN handlers are set to SIG_DFL. */
134 posix_spawnattr_t attr;
135 posix_spawnattr_init (&attr);
136 sigset_t mask;
137 sigemptyset (&mask);
138 sigaddset (&mask, SIGUSR1);
139 sigaddset (&mask, SIGUSR2);
140 posix_spawnattr_setsigdefault (&attr, &mask);
141 posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF);
142 spawn_signal_test ("SIG_DFL", &attr);
143 posix_spawnattr_destroy (&attr);
147 static int
148 do_test (int argc, char *argv[])
150 /* We must have either:
152 - one or four parameters if called initially:
153 + argv[1]: path for ld.so optional
154 + argv[2]: "--library-path" optional
155 + argv[3]: the library path optional
156 + argv[4]: the application name
158 - six parameters left if called through re-execution:
159 + argv[1]: the application name
160 + argv[2]: check SIG_IGN/SIG_DFL.
162 * When built with --enable-hardcoded-path-in-tests or issued without
163 using the loader directly. */
165 if (restart)
166 handle_restart (argc - 1, &argv[1]);
168 TEST_VERIFY_EXIT (argc == 2 || argc == 5);
170 int i;
171 for (i = 0; i < argc - 1; i++)
172 spargs[i] = argv[i + 1];
173 spargs[i++] = (char *) "--direct";
174 spargs[i++] = (char *) "--restart";
175 check_type_argc = i++;
176 spargs[i] = NULL;
179 do_test_signals ();
181 return 0;
184 #define TEST_FUNCTION_ARGV do_test
185 #include <support/test-driver.c>