xref: /aosp_15_r20/bionic/tests/spawn_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <spawn.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
22*8d67ca89SAndroid Build Coastguard Worker 
23*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
24*8d67ca89SAndroid Build Coastguard Worker 
25*8d67ca89SAndroid Build Coastguard Worker #include "SignalUtils.h"
26*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
27*8d67ca89SAndroid Build Coastguard Worker 
28*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
29*8d67ca89SAndroid Build Coastguard Worker #include <android-base/strings.h>
30*8d67ca89SAndroid Build Coastguard Worker 
31*8d67ca89SAndroid Build Coastguard Worker // Old versions of glibc didn't have POSIX_SPAWN_SETSID.
32*8d67ca89SAndroid Build Coastguard Worker #if __GLIBC__
33*8d67ca89SAndroid Build Coastguard Worker # if !defined(POSIX_SPAWN_SETSID)
34*8d67ca89SAndroid Build Coastguard Worker #  define POSIX_SPAWN_SETSID 0
35*8d67ca89SAndroid Build Coastguard Worker # endif
36*8d67ca89SAndroid Build Coastguard Worker #elif defined(__BIONIC__)
37*8d67ca89SAndroid Build Coastguard Worker #include <platform/bionic/reserved_signals.h>
38*8d67ca89SAndroid Build Coastguard Worker #endif
39*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_init_posix_spawnattr_destroy)40*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_init_posix_spawnattr_destroy) {
41*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
42*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
43*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
44*8d67ca89SAndroid Build Coastguard Worker }
45*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setflags_EINVAL)46*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setflags_EINVAL) {
47*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
48*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
49*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(EINVAL, posix_spawnattr_setflags(&sa, ~0));
50*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
51*8d67ca89SAndroid Build Coastguard Worker }
52*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setflags_posix_spawnattr_getflags)53*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setflags_posix_spawnattr_getflags) {
54*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
55*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
56*8d67ca89SAndroid Build Coastguard Worker 
57*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_RESETIDS));
58*8d67ca89SAndroid Build Coastguard Worker   short flags;
59*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getflags(&sa, &flags));
60*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(POSIX_SPAWN_RESETIDS, flags);
61*8d67ca89SAndroid Build Coastguard Worker 
62*8d67ca89SAndroid Build Coastguard Worker   constexpr short all_flags = POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF |
63*8d67ca89SAndroid Build Coastguard Worker                               POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSCHEDPARAM |
64*8d67ca89SAndroid Build Coastguard Worker                               POSIX_SPAWN_SETSCHEDULER | POSIX_SPAWN_USEVFORK | POSIX_SPAWN_SETSID;
65*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, all_flags));
66*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getflags(&sa, &flags));
67*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(all_flags, flags);
68*8d67ca89SAndroid Build Coastguard Worker 
69*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
70*8d67ca89SAndroid Build Coastguard Worker }
71*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setpgroup_posix_spawnattr_getpgroup)72*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setpgroup_posix_spawnattr_getpgroup) {
73*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
74*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
75*8d67ca89SAndroid Build Coastguard Worker 
76*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setpgroup(&sa, 123));
77*8d67ca89SAndroid Build Coastguard Worker   pid_t g;
78*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getpgroup(&sa, &g));
79*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(123, g);
80*8d67ca89SAndroid Build Coastguard Worker 
81*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
82*8d67ca89SAndroid Build Coastguard Worker }
83*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setsigmask_posix_spawnattr_getsigmask)84*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setsigmask_posix_spawnattr_getsigmask) {
85*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
86*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
87*8d67ca89SAndroid Build Coastguard Worker 
88*8d67ca89SAndroid Build Coastguard Worker   sigset_t sigs;
89*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigmask(&sa, &sigs));
90*8d67ca89SAndroid Build Coastguard Worker   ASSERT_FALSE(sigismember(&sigs, SIGALRM));
91*8d67ca89SAndroid Build Coastguard Worker 
92*8d67ca89SAndroid Build Coastguard Worker   sigset_t just_SIGALRM;
93*8d67ca89SAndroid Build Coastguard Worker   sigemptyset(&just_SIGALRM);
94*8d67ca89SAndroid Build Coastguard Worker   sigaddset(&just_SIGALRM, SIGALRM);
95*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setsigmask(&sa, &just_SIGALRM));
96*8d67ca89SAndroid Build Coastguard Worker 
97*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigmask(&sa, &sigs));
98*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(sigismember(&sigs, SIGALRM));
99*8d67ca89SAndroid Build Coastguard Worker 
100*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
101*8d67ca89SAndroid Build Coastguard Worker }
102*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64)103*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64) {
104*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
105*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
106*8d67ca89SAndroid Build Coastguard Worker 
107*8d67ca89SAndroid Build Coastguard Worker   sigset64_t sigs;
108*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
109*8d67ca89SAndroid Build Coastguard Worker   ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
110*8d67ca89SAndroid Build Coastguard Worker 
111*8d67ca89SAndroid Build Coastguard Worker   sigset64_t just_SIGRTMIN;
112*8d67ca89SAndroid Build Coastguard Worker   sigemptyset64(&just_SIGRTMIN);
113*8d67ca89SAndroid Build Coastguard Worker   sigaddset64(&just_SIGRTMIN, SIGRTMIN);
114*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setsigmask64(&sa, &just_SIGRTMIN));
115*8d67ca89SAndroid Build Coastguard Worker 
116*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
117*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
118*8d67ca89SAndroid Build Coastguard Worker 
119*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
120*8d67ca89SAndroid Build Coastguard Worker }
121*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault)122*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) {
123*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
124*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
125*8d67ca89SAndroid Build Coastguard Worker 
126*8d67ca89SAndroid Build Coastguard Worker   sigset_t sigs;
127*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigdefault(&sa, &sigs));
128*8d67ca89SAndroid Build Coastguard Worker   ASSERT_FALSE(sigismember(&sigs, SIGALRM));
129*8d67ca89SAndroid Build Coastguard Worker 
130*8d67ca89SAndroid Build Coastguard Worker   sigset_t just_SIGALRM;
131*8d67ca89SAndroid Build Coastguard Worker   sigemptyset(&just_SIGALRM);
132*8d67ca89SAndroid Build Coastguard Worker   sigaddset(&just_SIGALRM, SIGALRM);
133*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setsigdefault(&sa, &just_SIGALRM));
134*8d67ca89SAndroid Build Coastguard Worker 
135*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigdefault(&sa, &sigs));
136*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(sigismember(&sigs, SIGALRM));
137*8d67ca89SAndroid Build Coastguard Worker 
138*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
139*8d67ca89SAndroid Build Coastguard Worker }
140*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64)141*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64) {
142*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
143*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
144*8d67ca89SAndroid Build Coastguard Worker 
145*8d67ca89SAndroid Build Coastguard Worker   sigset64_t sigs;
146*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
147*8d67ca89SAndroid Build Coastguard Worker   ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
148*8d67ca89SAndroid Build Coastguard Worker 
149*8d67ca89SAndroid Build Coastguard Worker   sigset64_t just_SIGRTMIN;
150*8d67ca89SAndroid Build Coastguard Worker   sigemptyset64(&just_SIGRTMIN);
151*8d67ca89SAndroid Build Coastguard Worker   sigaddset64(&just_SIGRTMIN, SIGRTMIN);
152*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setsigdefault64(&sa, &just_SIGRTMIN));
153*8d67ca89SAndroid Build Coastguard Worker 
154*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
155*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
156*8d67ca89SAndroid Build Coastguard Worker 
157*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
158*8d67ca89SAndroid Build Coastguard Worker }
159*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam)160*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam) {
161*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
162*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
163*8d67ca89SAndroid Build Coastguard Worker 
164*8d67ca89SAndroid Build Coastguard Worker   sched_param sp;
165*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getschedparam(&sa, &sp));
166*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, sp.sched_priority);
167*8d67ca89SAndroid Build Coastguard Worker 
168*8d67ca89SAndroid Build Coastguard Worker   sched_param sp123 = { .sched_priority = 123 };
169*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setschedparam(&sa, &sp123));
170*8d67ca89SAndroid Build Coastguard Worker 
171*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getschedparam(&sa, &sp));
172*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(123, sp.sched_priority);
173*8d67ca89SAndroid Build Coastguard Worker 
174*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
175*8d67ca89SAndroid Build Coastguard Worker }
176*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnattr_setschedpolicy_posix_spawnattr_getschedpolicy)177*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnattr_setschedpolicy_posix_spawnattr_getschedpolicy) {
178*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
179*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
180*8d67ca89SAndroid Build Coastguard Worker 
181*8d67ca89SAndroid Build Coastguard Worker   int p;
182*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getschedpolicy(&sa, &p));
183*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, p);
184*8d67ca89SAndroid Build Coastguard Worker 
185*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setschedpolicy(&sa, SCHED_FIFO));
186*8d67ca89SAndroid Build Coastguard Worker 
187*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_getschedpolicy(&sa, &p));
188*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(SCHED_FIFO, p);
189*8d67ca89SAndroid Build Coastguard Worker 
190*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
191*8d67ca89SAndroid Build Coastguard Worker }
192*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn)193*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn) {
194*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
195*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({BIN_DIR "true", nullptr});
196*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
197*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
198*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 0);
199*8d67ca89SAndroid Build Coastguard Worker }
200*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_not_found)201*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_not_found) {
202*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
203*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"true", nullptr});
204*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
205*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
206*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 127);
207*8d67ca89SAndroid Build Coastguard Worker }
208*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnp)209*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnp) {
210*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
211*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"true", nullptr});
212*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
213*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
214*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 0);
215*8d67ca89SAndroid Build Coastguard Worker }
216*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawnp_not_found)217*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawnp_not_found) {
218*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
219*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"does-not-exist", nullptr});
220*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
221*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), nullptr));
222*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 127);
223*8d67ca89SAndroid Build Coastguard Worker }
224*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_environment)225*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_environment) {
226*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
227*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"sh", "-c", "exit $posix_spawn_environment_test", nullptr});
228*8d67ca89SAndroid Build Coastguard Worker   eth.SetEnv({"posix_spawn_environment_test=66", nullptr});
229*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
230*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), nullptr, nullptr, eth.GetArgs(), eth.GetEnv()));
231*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 66);
232*8d67ca89SAndroid Build Coastguard Worker }
233*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_file_actions)234*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_file_actions) {
235*8d67ca89SAndroid Build Coastguard Worker #if !defined(__GLIBC__)
236*8d67ca89SAndroid Build Coastguard Worker   int fds[2];
237*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, pipe(fds));
238*8d67ca89SAndroid Build Coastguard Worker 
239*8d67ca89SAndroid Build Coastguard Worker   posix_spawn_file_actions_t fa;
240*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_init(&fa));
241*8d67ca89SAndroid Build Coastguard Worker 
242*8d67ca89SAndroid Build Coastguard Worker   // Test addclose and adddup2 by redirecting output to the pipe created above.
243*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
244*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
245*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
246*8d67ca89SAndroid Build Coastguard Worker   // Check that close(2) failures are ignored by closing the same fd again.
247*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
248*8d67ca89SAndroid Build Coastguard Worker   // Open a file directly, to test addopen.
249*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 56, "/proc/version", O_RDONLY, 0));
250*8d67ca89SAndroid Build Coastguard Worker   // Test addfchdir by opening the same file a second way...
251*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 57, "/proc", O_PATH, 0));
252*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addfchdir_np(&fa, 57));
253*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 58, "version", O_RDONLY, 0));
254*8d67ca89SAndroid Build Coastguard Worker   // Test addchdir by opening the same file a third way...
255*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addchdir_np(&fa, "/"));
256*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 59, "proc/version", O_RDONLY, 0));
257*8d67ca89SAndroid Build Coastguard Worker 
258*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
259*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"ls", "-l", "/proc/self/fd", nullptr});
260*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
261*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), &fa, nullptr, eth.GetArgs(), eth.GetEnv()));
262*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_destroy(&fa));
263*8d67ca89SAndroid Build Coastguard Worker 
264*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, close(fds[1]));
265*8d67ca89SAndroid Build Coastguard Worker   std::string content;
266*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFdToString(fds[0], &content));
267*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, close(fds[0]));
268*8d67ca89SAndroid Build Coastguard Worker 
269*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 0);
270*8d67ca89SAndroid Build Coastguard Worker 
271*8d67ca89SAndroid Build Coastguard Worker   // We'll know the dup2 worked if we see any ls(1) output in our pipe.
272*8d67ca89SAndroid Build Coastguard Worker   // The opens we can check manually (and they implicitly check the chdirs)...
273*8d67ca89SAndroid Build Coastguard Worker   bool open_to_fd_56_worked = false;
274*8d67ca89SAndroid Build Coastguard Worker   bool open_to_fd_58_worked = false;
275*8d67ca89SAndroid Build Coastguard Worker   bool open_to_fd_59_worked = false;
276*8d67ca89SAndroid Build Coastguard Worker   for (const auto& line : android::base::Split(content, "\n")) {
277*8d67ca89SAndroid Build Coastguard Worker     if (line.find(" 56 -> /proc/version") != std::string::npos) open_to_fd_56_worked = true;
278*8d67ca89SAndroid Build Coastguard Worker     if (line.find(" 58 -> /proc/version") != std::string::npos) open_to_fd_58_worked = true;
279*8d67ca89SAndroid Build Coastguard Worker     if (line.find(" 59 -> /proc/version") != std::string::npos) open_to_fd_59_worked = true;
280*8d67ca89SAndroid Build Coastguard Worker   }
281*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(open_to_fd_56_worked) << content;
282*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(open_to_fd_58_worked) << content;
283*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(open_to_fd_59_worked) << content;
284*8d67ca89SAndroid Build Coastguard Worker #else
285*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "our old glibc doesn't have the chdirs; newer versions and musl do.";
286*8d67ca89SAndroid Build Coastguard Worker #endif
287*8d67ca89SAndroid Build Coastguard Worker }
288*8d67ca89SAndroid Build Coastguard Worker 
CatFileToString(posix_spawnattr_t * sa,const char * path,std::string * content)289*8d67ca89SAndroid Build Coastguard Worker static void CatFileToString(posix_spawnattr_t* sa, const char* path, std::string* content) {
290*8d67ca89SAndroid Build Coastguard Worker   int fds[2];
291*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, pipe(fds));
292*8d67ca89SAndroid Build Coastguard Worker 
293*8d67ca89SAndroid Build Coastguard Worker   posix_spawn_file_actions_t fa;
294*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_init(&fa));
295*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
296*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
297*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
298*8d67ca89SAndroid Build Coastguard Worker 
299*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
300*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"cat", path, nullptr});
301*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
302*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), &fa, sa, eth.GetArgs(), nullptr));
303*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_destroy(&fa));
304*8d67ca89SAndroid Build Coastguard Worker 
305*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, close(fds[1]));
306*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFdToString(fds[0], content));
307*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, close(fds[0]));
308*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 0);
309*8d67ca89SAndroid Build Coastguard Worker }
310*8d67ca89SAndroid Build Coastguard Worker 
311*8d67ca89SAndroid Build Coastguard Worker struct ProcStat {
312*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
313*8d67ca89SAndroid Build Coastguard Worker   pid_t ppid;
314*8d67ca89SAndroid Build Coastguard Worker   pid_t pgrp;
315*8d67ca89SAndroid Build Coastguard Worker   pid_t sid;
316*8d67ca89SAndroid Build Coastguard Worker };
317*8d67ca89SAndroid Build Coastguard Worker 
GetChildStat(posix_spawnattr_t * sa,ProcStat * ps)318*8d67ca89SAndroid Build Coastguard Worker static __attribute__((unused)) void GetChildStat(posix_spawnattr_t* sa, ProcStat* ps) {
319*8d67ca89SAndroid Build Coastguard Worker   std::string content;
320*8d67ca89SAndroid Build Coastguard Worker   CatFileToString(sa, "/proc/self/stat", &content);
321*8d67ca89SAndroid Build Coastguard Worker 
322*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(4, sscanf(content.c_str(), "%d (cat) %*c %d %d %d", &ps->pid, &ps->ppid, &ps->pgrp,
323*8d67ca89SAndroid Build Coastguard Worker                       &ps->sid));
324*8d67ca89SAndroid Build Coastguard Worker 
325*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(getpid(), ps->ppid);
326*8d67ca89SAndroid Build Coastguard Worker }
327*8d67ca89SAndroid Build Coastguard Worker 
328*8d67ca89SAndroid Build Coastguard Worker struct ProcStatus {
329*8d67ca89SAndroid Build Coastguard Worker   uint64_t sigblk;
330*8d67ca89SAndroid Build Coastguard Worker   uint64_t sigign;
331*8d67ca89SAndroid Build Coastguard Worker };
332*8d67ca89SAndroid Build Coastguard Worker 
GetChildStatus(posix_spawnattr_t * sa,ProcStatus * ps)333*8d67ca89SAndroid Build Coastguard Worker static void __attribute__((unused)) GetChildStatus(posix_spawnattr_t* sa, ProcStatus* ps) {
334*8d67ca89SAndroid Build Coastguard Worker   std::string content;
335*8d67ca89SAndroid Build Coastguard Worker   CatFileToString(sa, "/proc/self/status", &content);
336*8d67ca89SAndroid Build Coastguard Worker 
337*8d67ca89SAndroid Build Coastguard Worker   bool saw_blk = false;
338*8d67ca89SAndroid Build Coastguard Worker   bool saw_ign = false;
339*8d67ca89SAndroid Build Coastguard Worker   for (const auto& line : android::base::Split(content, "\n")) {
340*8d67ca89SAndroid Build Coastguard Worker     if (sscanf(line.c_str(), "SigBlk: %" SCNx64, &ps->sigblk) == 1) saw_blk = true;
341*8d67ca89SAndroid Build Coastguard Worker     if (sscanf(line.c_str(), "SigIgn: %" SCNx64, &ps->sigign) == 1) saw_ign = true;
342*8d67ca89SAndroid Build Coastguard Worker   }
343*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(saw_blk);
344*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(saw_ign);
345*8d67ca89SAndroid Build Coastguard Worker }
346*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_POSIX_SPAWN_SETSID_clear)347*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_POSIX_SPAWN_SETSID_clear) {
348*8d67ca89SAndroid Build Coastguard Worker   pid_t parent_sid = getsid(0);
349*8d67ca89SAndroid Build Coastguard Worker 
350*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
351*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
352*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, 0));
353*8d67ca89SAndroid Build Coastguard Worker 
354*8d67ca89SAndroid Build Coastguard Worker   ProcStat ps = {};
355*8d67ca89SAndroid Build Coastguard Worker   GetChildStat(&sa, &ps);
356*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(parent_sid, ps.sid);
357*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
358*8d67ca89SAndroid Build Coastguard Worker }
359*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_POSIX_SPAWN_SETSID_set)360*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_POSIX_SPAWN_SETSID_set) {
361*8d67ca89SAndroid Build Coastguard Worker   pid_t parent_sid = getsid(0);
362*8d67ca89SAndroid Build Coastguard Worker 
363*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
364*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
365*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSID));
366*8d67ca89SAndroid Build Coastguard Worker 
367*8d67ca89SAndroid Build Coastguard Worker   ProcStat ps = {};
368*8d67ca89SAndroid Build Coastguard Worker   GetChildStat(&sa, &ps);
369*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(parent_sid, ps.sid);
370*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
371*8d67ca89SAndroid Build Coastguard Worker }
372*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_POSIX_SPAWN_SETPGROUP_clear)373*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_POSIX_SPAWN_SETPGROUP_clear) {
374*8d67ca89SAndroid Build Coastguard Worker   pid_t parent_pgrp = getpgrp();
375*8d67ca89SAndroid Build Coastguard Worker 
376*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
377*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
378*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, 0));
379*8d67ca89SAndroid Build Coastguard Worker 
380*8d67ca89SAndroid Build Coastguard Worker   ProcStat ps = {};
381*8d67ca89SAndroid Build Coastguard Worker   GetChildStat(&sa, &ps);
382*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(parent_pgrp, ps.pgrp);
383*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
384*8d67ca89SAndroid Build Coastguard Worker }
385*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_POSIX_SPAWN_SETPGROUP_set)386*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_POSIX_SPAWN_SETPGROUP_set) {
387*8d67ca89SAndroid Build Coastguard Worker   pid_t parent_pgrp = getpgrp();
388*8d67ca89SAndroid Build Coastguard Worker 
389*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
390*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
391*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setpgroup(&sa, 0));
392*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETPGROUP));
393*8d67ca89SAndroid Build Coastguard Worker 
394*8d67ca89SAndroid Build Coastguard Worker   ProcStat ps = {};
395*8d67ca89SAndroid Build Coastguard Worker   GetChildStat(&sa, &ps);
396*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(parent_pgrp, ps.pgrp);
397*8d67ca89SAndroid Build Coastguard Worker   // Setting pgid 0 means "the same as the caller's pid".
398*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(ps.pid, ps.pgrp);
399*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
400*8d67ca89SAndroid Build Coastguard Worker }
401*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_POSIX_SPAWN_SETSIGMASK)402*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGMASK) {
403*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
404*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "glibc doesn't ignore the same signals.";
405*8d67ca89SAndroid Build Coastguard Worker #else
406*8d67ca89SAndroid Build Coastguard Worker   // Block SIGBUS in the parent...
407*8d67ca89SAndroid Build Coastguard Worker   sigset_t just_SIGBUS;
408*8d67ca89SAndroid Build Coastguard Worker   sigemptyset(&just_SIGBUS);
409*8d67ca89SAndroid Build Coastguard Worker   sigaddset(&just_SIGBUS, SIGBUS);
410*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGBUS, nullptr));
411*8d67ca89SAndroid Build Coastguard Worker 
412*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
413*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
414*8d67ca89SAndroid Build Coastguard Worker 
415*8d67ca89SAndroid Build Coastguard Worker   // Ask for only SIGALRM to be blocked in the child...
416*8d67ca89SAndroid Build Coastguard Worker   sigset_t just_SIGALRM;
417*8d67ca89SAndroid Build Coastguard Worker   sigemptyset(&just_SIGALRM);
418*8d67ca89SAndroid Build Coastguard Worker   sigaddset(&just_SIGALRM, SIGALRM);
419*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setsigmask(&sa, &just_SIGALRM));
420*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGMASK));
421*8d67ca89SAndroid Build Coastguard Worker 
422*8d67ca89SAndroid Build Coastguard Worker   // Check that's what happens...
423*8d67ca89SAndroid Build Coastguard Worker   ProcStatus ps = {};
424*8d67ca89SAndroid Build Coastguard Worker   GetChildStatus(&sa, &ps);
425*8d67ca89SAndroid Build Coastguard Worker 
426*8d67ca89SAndroid Build Coastguard Worker   // TIMER_SIGNAL should also be blocked.
427*8d67ca89SAndroid Build Coastguard Worker   uint64_t expected_blocked = 0;
428*8d67ca89SAndroid Build Coastguard Worker   SignalSetAdd(&expected_blocked, SIGALRM);
429*8d67ca89SAndroid Build Coastguard Worker   SignalSetAdd(&expected_blocked, BIONIC_SIGNAL_POSIX_TIMERS);
430*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(expected_blocked, ps.sigblk);
431*8d67ca89SAndroid Build Coastguard Worker 
432*8d67ca89SAndroid Build Coastguard Worker   uint64_t expected_ignored = 0;
433*8d67ca89SAndroid Build Coastguard Worker   SignalSetAdd(&expected_ignored, BIONIC_SIGNAL_ART_PROFILER);
434*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(expected_ignored, ps.sigign);
435*8d67ca89SAndroid Build Coastguard Worker 
436*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
437*8d67ca89SAndroid Build Coastguard Worker #endif
438*8d67ca89SAndroid Build Coastguard Worker }
439*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_POSIX_SPAWN_SETSIGDEF)440*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_POSIX_SPAWN_SETSIGDEF) {
441*8d67ca89SAndroid Build Coastguard Worker #if defined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
442*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "glibc doesn't ignore the same signals.";
443*8d67ca89SAndroid Build Coastguard Worker #else
444*8d67ca89SAndroid Build Coastguard Worker   // Ignore SIGALRM and SIGCONT in the parent...
445*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(SIG_ERR, signal(SIGALRM, SIG_IGN));
446*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(SIG_ERR, signal(SIGCONT, SIG_IGN));
447*8d67ca89SAndroid Build Coastguard Worker 
448*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t sa;
449*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_init(&sa));
450*8d67ca89SAndroid Build Coastguard Worker 
451*8d67ca89SAndroid Build Coastguard Worker   // Ask for SIGALRM to be defaulted in the child...
452*8d67ca89SAndroid Build Coastguard Worker   sigset_t just_SIGALRM;
453*8d67ca89SAndroid Build Coastguard Worker   sigemptyset(&just_SIGALRM);
454*8d67ca89SAndroid Build Coastguard Worker   sigaddset(&just_SIGALRM, SIGALRM);
455*8d67ca89SAndroid Build Coastguard Worker 
456*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setsigdefault(&sa, &just_SIGALRM));
457*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGDEF));
458*8d67ca89SAndroid Build Coastguard Worker 
459*8d67ca89SAndroid Build Coastguard Worker   // Check that's what happens...
460*8d67ca89SAndroid Build Coastguard Worker   ProcStatus ps = {};
461*8d67ca89SAndroid Build Coastguard Worker   GetChildStatus(&sa, &ps);
462*8d67ca89SAndroid Build Coastguard Worker 
463*8d67ca89SAndroid Build Coastguard Worker   // TIMER_SIGNAL should be blocked.
464*8d67ca89SAndroid Build Coastguard Worker   uint64_t expected_blocked = 0;
465*8d67ca89SAndroid Build Coastguard Worker   SignalSetAdd(&expected_blocked, BIONIC_SIGNAL_POSIX_TIMERS);
466*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(expected_blocked, ps.sigblk);
467*8d67ca89SAndroid Build Coastguard Worker 
468*8d67ca89SAndroid Build Coastguard Worker   uint64_t expected_ignored = 0;
469*8d67ca89SAndroid Build Coastguard Worker   SignalSetAdd(&expected_ignored, SIGCONT);
470*8d67ca89SAndroid Build Coastguard Worker   SignalSetAdd(&expected_ignored, BIONIC_SIGNAL_ART_PROFILER);
471*8d67ca89SAndroid Build Coastguard Worker   EXPECT_EQ(expected_ignored, ps.sigign);
472*8d67ca89SAndroid Build Coastguard Worker 
473*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
474*8d67ca89SAndroid Build Coastguard Worker #endif
475*8d67ca89SAndroid Build Coastguard Worker }
476*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,signal_stress)477*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, signal_stress) {
478*8d67ca89SAndroid Build Coastguard Worker   // Ensure that posix_spawn doesn't restore the caller's signal mask in the
479*8d67ca89SAndroid Build Coastguard Worker   // child without first defaulting any caught signals (http://b/68707996).
480*8d67ca89SAndroid Build Coastguard Worker   static pid_t parent = getpid();
481*8d67ca89SAndroid Build Coastguard Worker 
482*8d67ca89SAndroid Build Coastguard Worker   setpgid(0, 0);
483*8d67ca89SAndroid Build Coastguard Worker   signal(SIGRTMIN, SIG_IGN);
484*8d67ca89SAndroid Build Coastguard Worker 
485*8d67ca89SAndroid Build Coastguard Worker   pid_t pid = fork();
486*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, pid);
487*8d67ca89SAndroid Build Coastguard Worker 
488*8d67ca89SAndroid Build Coastguard Worker   if (pid == 0) {
489*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < 1024; ++i) {
490*8d67ca89SAndroid Build Coastguard Worker       kill(0, SIGRTMIN);
491*8d67ca89SAndroid Build Coastguard Worker       usleep(10);
492*8d67ca89SAndroid Build Coastguard Worker     }
493*8d67ca89SAndroid Build Coastguard Worker     _exit(99);
494*8d67ca89SAndroid Build Coastguard Worker   }
495*8d67ca89SAndroid Build Coastguard Worker 
496*8d67ca89SAndroid Build Coastguard Worker   // We test both with and without attributes, because they used to be
497*8d67ca89SAndroid Build Coastguard Worker   // different codepaths. We also test with an empty `sigdefault` set.
498*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t attr1;
499*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_init(&attr1);
500*8d67ca89SAndroid Build Coastguard Worker 
501*8d67ca89SAndroid Build Coastguard Worker   sigset_t empty_mask = {};
502*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t attr2;
503*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_init(&attr2);
504*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_setflags(&attr2, POSIX_SPAWN_SETSIGDEF);
505*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_setsigdefault(&attr2, &empty_mask);
506*8d67ca89SAndroid Build Coastguard Worker 
507*8d67ca89SAndroid Build Coastguard Worker   posix_spawnattr_t* attrs[] = { nullptr, &attr1, &attr2 };
508*8d67ca89SAndroid Build Coastguard Worker 
509*8d67ca89SAndroid Build Coastguard Worker   // We use a real-time signal because that's a tricky case for LP32
510*8d67ca89SAndroid Build Coastguard Worker   // because our sigset_t was too small.
511*8d67ca89SAndroid Build Coastguard Worker   ScopedSignalHandler ssh(SIGRTMIN, [](int) { ASSERT_EQ(getpid(), parent); });
512*8d67ca89SAndroid Build Coastguard Worker 
513*8d67ca89SAndroid Build Coastguard Worker   const size_t pid_count = 128;
514*8d67ca89SAndroid Build Coastguard Worker   pid_t spawned_pids[pid_count];
515*8d67ca89SAndroid Build Coastguard Worker 
516*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
517*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"true", nullptr});
518*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < pid_count; ++i) {
519*8d67ca89SAndroid Build Coastguard Worker     pid_t spawned_pid;
520*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(0, posix_spawn(&spawned_pid, "true", nullptr, attrs[i % 3], eth.GetArgs(), nullptr));
521*8d67ca89SAndroid Build Coastguard Worker     spawned_pids[i] = spawned_pid;
522*8d67ca89SAndroid Build Coastguard Worker   }
523*8d67ca89SAndroid Build Coastguard Worker 
524*8d67ca89SAndroid Build Coastguard Worker   for (pid_t spawned_pid : spawned_pids) {
525*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(spawned_pid, TEMP_FAILURE_RETRY(waitpid(spawned_pid, nullptr, 0)));
526*8d67ca89SAndroid Build Coastguard Worker   }
527*8d67ca89SAndroid Build Coastguard Worker 
528*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 99);
529*8d67ca89SAndroid Build Coastguard Worker }
530*8d67ca89SAndroid Build Coastguard Worker 
TEST(spawn,posix_spawn_dup2_CLOEXEC)531*8d67ca89SAndroid Build Coastguard Worker TEST(spawn, posix_spawn_dup2_CLOEXEC) {
532*8d67ca89SAndroid Build Coastguard Worker   int fds[2];
533*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, pipe(fds));
534*8d67ca89SAndroid Build Coastguard Worker 
535*8d67ca89SAndroid Build Coastguard Worker   posix_spawn_file_actions_t fa;
536*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_init(&fa));
537*8d67ca89SAndroid Build Coastguard Worker 
538*8d67ca89SAndroid Build Coastguard Worker   int fd = open("/proc/version", O_RDONLY | O_CLOEXEC);
539*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, fd);
540*8d67ca89SAndroid Build Coastguard Worker 
541*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
542*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
543*8d67ca89SAndroid Build Coastguard Worker   // dup2() is a no-op when the two fds are the same, so this won't clear
544*8d67ca89SAndroid Build Coastguard Worker   // O_CLOEXEC unless we're doing extra work to make that happen.
545*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fd, fd));
546*8d67ca89SAndroid Build Coastguard Worker 
547*8d67ca89SAndroid Build Coastguard Worker   // Read /proc/self/fd/<fd> in the child...
548*8d67ca89SAndroid Build Coastguard Worker   std::string fdinfo_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
549*8d67ca89SAndroid Build Coastguard Worker   ExecTestHelper eth;
550*8d67ca89SAndroid Build Coastguard Worker   eth.SetArgs({"cat", fdinfo_path.c_str(), nullptr});
551*8d67ca89SAndroid Build Coastguard Worker   pid_t pid;
552*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawnp(&pid, eth.GetArg0(), &fa, nullptr, eth.GetArgs(), eth.GetEnv()));
553*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, posix_spawn_file_actions_destroy(&fa));
554*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, close(fds[1]));
555*8d67ca89SAndroid Build Coastguard Worker   std::string content;
556*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFdToString(fds[0], &content));
557*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, close(fds[0]));
558*8d67ca89SAndroid Build Coastguard Worker 
559*8d67ca89SAndroid Build Coastguard Worker   // ...and compare that to the parent. This is overkill really, since the very
560*8d67ca89SAndroid Build Coastguard Worker   // fact that the child had a valid file descriptor strongly implies that we
561*8d67ca89SAndroid Build Coastguard Worker   // removed O_CLOEXEC, but we may as well check that the child ended up with
562*8d67ca89SAndroid Build Coastguard Worker   // the *right* file descriptor :-)
563*8d67ca89SAndroid Build Coastguard Worker   std::string expected;
564*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(android::base::ReadFdToString(fd, &expected));
565*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(expected, content);
566*8d67ca89SAndroid Build Coastguard Worker 
567*8d67ca89SAndroid Build Coastguard Worker   AssertChildExited(pid, 0);
568*8d67ca89SAndroid Build Coastguard Worker }
569