1/* Test posix_spawn setsid attribute.
2 Copyright (C) 2017-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 <https://www.gnu.org/licenses/>. */
18
19#include <errno.h>
20#include <fcntl.h>
21#include <getopt.h>
22#include <intprops.h>
23#include <paths.h>
24#include <spawn.h>
25#include <stdbool.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <sys/resource.h>
29#include <sys/wait.h>
30#include <unistd.h>
31
32#include <support/check.h>
33#include <support/xunistd.h>
34#include <support/temp_file.h>
35#include <tst-spawn.h>
36
37/* Nonzero if the program gets called via `exec'. */
38static int restart;
39
40/* Hold the four initial argument used to respawn the process, plus
41 the extra '--direct' and '--restart', and a final NULL. */
42static char *initial_argv[7];
43static int initial_argv_count;
44
45#define CMDLINE_OPTIONS \
46 { "restart", no_argument, &restart, 1 },
47
48static char *pidfile;
49
50static pid_t
51read_child_sid (void)
52{
53 int pidfd = xopen (path: pidfile, O_RDONLY, 0);
54
55 char buf[INT_STRLEN_BOUND (pid_t)];
56 ssize_t n = read (pidfd, buf, sizeof (buf));
57 TEST_VERIFY (n < sizeof buf && n >= 0);
58 buf[n] = '\0';
59
60 /* We only expect to read the PID. */
61 char *endp;
62 long int rpid = strtol (buf, &endp, 10);
63 TEST_VERIFY (endp != buf);
64
65 xclose (pidfd);
66
67 return rpid;
68}
69
70/* Called on process re-execution, write down the session id on PIDFILE. */
71static void
72handle_restart (const char *pidfile)
73{
74 int pidfd = xopen (path: pidfile, O_WRONLY, 0);
75
76 char buf[INT_STRLEN_BOUND (pid_t)];
77 int s = snprintf (s: buf, maxlen: sizeof buf, format: "%d", getsid (0));
78 size_t n = write (pidfd, buf, s);
79 TEST_VERIFY (n == s);
80
81 xclose (pidfd);
82}
83
84static void
85do_test_setsid (bool test_setsid)
86{
87 /* Current session ID. */
88 pid_t sid = getsid (0);
89 TEST_VERIFY (sid != (pid_t) -1);
90
91 posix_spawnattr_t attrp;
92 TEST_COMPARE (posix_spawnattr_init (&attrp), 0);
93 if (test_setsid)
94 TEST_COMPARE (posix_spawnattr_setflags (&attrp, POSIX_SPAWN_SETSID), 0);
95
96 /* 1 or 4 elements from initial_argv:
97 + path to ld.so optional
98 + --library-path optional
99 + the library path optional
100 + application name
101 + --direct
102 + --restart
103 + pidfile */
104 int argv_size = initial_argv_count + 2;
105 char *args[argv_size];
106 int argc = 0;
107
108 for (char **arg = initial_argv; *arg != NULL; arg++)
109 args[argc++] = *arg;
110 args[argc++] = pidfile;
111 args[argc] = NULL;
112 TEST_VERIFY (argc < argv_size);
113
114 PID_T_TYPE pid;
115 TEST_COMPARE (POSIX_SPAWN (&pid, args[0], NULL, &attrp, args, environ), 0);
116 TEST_COMPARE (posix_spawnattr_destroy (&attrp), 0);
117
118 siginfo_t sinfo;
119 TEST_COMPARE (WAITID (P_PID, pid, &sinfo, WEXITED), 0);
120 TEST_COMPARE (sinfo.si_code, CLD_EXITED);
121 TEST_COMPARE (sinfo.si_status, 0);
122
123 pid_t child_sid = read_child_sid ();
124
125 /* Child should have a different session ID than parent. */
126 TEST_VERIFY (child_sid != (pid_t) -1);
127
128 if (test_setsid)
129 TEST_VERIFY (child_sid != sid);
130 else
131 TEST_VERIFY (child_sid == sid);
132}
133
134static int
135do_test (int argc, char *argv[])
136{
137 /* We must have either:
138
139 - one or four parameters if called initially:
140 + argv[1]: path for ld.so optional
141 + argv[2]: "--library-path" optional
142 + argv[3]: the library path optional
143 + argv[4]: the application name
144
145 - six parameters left if called through re-execution:
146 + argv[5/1]: the application name
147 + argv[6/2]: the pidfile
148
149 * When built with --enable-hardcoded-path-in-tests or issued without
150 using the loader directly. */
151
152 if (restart)
153 {
154 handle_restart (pidfile: argv[1]);
155 return 0;
156 }
157
158 TEST_VERIFY_EXIT (argc == 2 || argc == 5);
159
160 int i;
161 for (i = 0; i < argc - 1; i++)
162 initial_argv[i] = argv[i + 1];
163 initial_argv[i++] = (char *) "--direct";
164 initial_argv[i++] = (char *) "--restart";
165 initial_argv_count = i;
166
167 create_temp_file (base: "tst-posix_spawn-setsid-", filename: &pidfile);
168
169 do_test_setsid (false);
170 do_test_setsid (true);
171
172 return 0;
173}
174
175#define TEST_FUNCTION_ARGV do_test
176#include <support/test-driver.c>
177

source code of glibc/posix/tst-posix_spawn-setsid.c