Skip to content

Commit e5fd9cc

Browse files
committed
tests: fall back to fork() if posix_spawnp() is not available
Android only started supporting posix_spawnp() in API level 28 (Android 9), so it is not going to be available on most devices. If the system doesn't provide it, then fall back to using fork() and execve().
1 parent 30eeb14 commit e5fd9cc

File tree

6 files changed

+55
-5
lines changed

6 files changed

+55
-5
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ check_function_exists(mach_approximate_time HAVE_MACH_APPROXIMATE_TIME)
190190
check_function_exists(mach_port_construct HAVE_MACH_PORT_CONSTRUCT)
191191
check_function_exists(malloc_create_zone HAVE_MALLOC_CREATE_ZONE)
192192
check_function_exists(posix_fadvise HAVE_POSIX_FADVISE)
193+
check_function_exists(posix_spawnp HAVE_POSIX_SPAWNP)
193194
check_function_exists(pthread_key_init_np HAVE_PTHREAD_KEY_INIT_NP)
194195
check_function_exists(pthread_main_np HAVE_PTHREAD_MAIN_NP)
195196
check_function_exists(pthread_workqueue_setdispatch_np HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP)

cmake/config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@
135135
/* Define to 1 if you have the `posix_fadvise' function. */
136136
#cmakedefine HAVE_POSIX_FADVISE
137137

138+
/* Define to 1 if you have the `posix_spawnp' function. */
139+
#cmakedefine HAVE_POSIX_SPAWNP
140+
138141
/* Define to 1 if you have the `pthread_key_init_np' function. */
139142
#cmakedefine HAVE_PTHREAD_KEY_INIT_NP
140143

tests/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ target_include_directories(bsdtests
2727
PRIVATE
2828
${CMAKE_CURRENT_BINARY_DIR}
2929
${CMAKE_CURRENT_SOURCE_DIR}
30-
${PROJECT_SOURCE_DIR})
30+
${PROJECT_SOURCE_DIR}
31+
PUBLIC
32+
# bsdtests.h needs config_ac.h
33+
${PROJECT_BINARY_DIR})
3134
if(BSD_OVERLAY_FOUND)
3235
target_compile_options(bsdtests
3336
PRIVATE

tests/bsdtestharness.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,21 @@ main(int argc, char *argv[])
6060
exit(1);
6161
}
6262

63+
#ifdef HAVE_POSIX_SPAWNP
64+
short spawnflags = 0;
6365
#ifdef __APPLE__
64-
short spawnflags = POSIX_SPAWN_START_SUSPENDED;
66+
spawnflags |= POSIX_SPAWN_START_SUSPENDED;
6567
#if TARGET_OS_EMBEDDED
6668
spawnflags |= POSIX_SPAWN_SETEXEC;
6769
#endif
68-
#else
69-
#define POSIX_SPAWN_SETEXEC 0 /* ignore... */
70-
short spawnflags = 0;
7170
#endif
7271

7372
posix_spawnattr_t attr;
7473
res = posix_spawnattr_init(&attr);
7574
assert(res == 0);
7675
res = posix_spawnattr_setflags(&attr, spawnflags);
7776
assert(res == 0);
77+
#endif
7878

7979
uint64_t to = 0;
8080
char *tos = getenv("BSDTEST_TIMEOUT");
@@ -104,9 +104,12 @@ main(int argc, char *argv[])
104104
struct timeval tv_start;
105105
gettimeofday(&tv_start, NULL);
106106

107+
#ifdef HAVE_POSIX_SPAWNP
108+
#ifdef __APPLE__
107109
if (spawnflags & POSIX_SPAWN_SETEXEC) {
108110
pid = fork();
109111
}
112+
#endif
110113
if (!pid) {
111114
res = posix_spawnp(&pid, newargv[0], NULL, &attr, newargv, environ);
112115
if (res) {
@@ -115,6 +118,22 @@ main(int argc, char *argv[])
115118
exit(EXIT_FAILURE);
116119
}
117120
}
121+
#elif defined(__unix__)
122+
(void)res;
123+
pid = fork();
124+
if (pid == -1) {
125+
perror("fork");
126+
exit(EXIT_FAILURE);
127+
} else if (pid == 0) {
128+
// Child process
129+
if (execve(newargv[0], newargv, environ) == -1) {
130+
perror(newargv[0]);
131+
_Exit(EXIT_FAILURE);
132+
}
133+
}
134+
#else
135+
#error "bsdtestharness not implemented on this platform"
136+
#endif
118137

119138
//fprintf(stderr, "pid = %d\n", pid);
120139
assert(pid > 0);

tests/bsdtests.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121
#ifndef __BSD_TEST_H__
2222
#define __BSD_TEST_H__
2323

24+
#if defined(HAVE_CONFIG_H)
25+
#if __has_include(<config/config_ac.h>)
26+
#include <config/config_ac.h>
27+
#else
28+
#include <config/config.h>
29+
#endif
30+
#endif
31+
2432

2533
#if !HAVE_PRINTFLIKE
2634
#ifndef __printflike

tests/dispatch_io_net.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,28 @@ main(int argc, char** argv)
218218
arguments[1] = port_str;
219219
arguments[2] = NULL;
220220

221+
#ifdef HAVE_POSIX_SPAWNP
221222
int error;
222223
if ((error = posix_spawnp(&clientid, exec_filename, NULL, NULL,
223224
arguments, environ)) != 0) {
224225
test_errno("Server-posix_spawnp()", error, 0);
225226
test_stop();
226227
}
228+
#elif defined(__unix__)
229+
clientid = fork();
230+
if (clientid == -1) {
231+
test_errno("Server-fork()", errno, 0);
232+
test_stop();
233+
} else if (clientid == 0) {
234+
// Child process
235+
if (execve(exec_filename, arguments, environ) == -1) {
236+
perror(exec_filename);
237+
_Exit(EXIT_FAILURE);
238+
}
239+
}
240+
#else
241+
#error "dispatch_io_net not implemented on this platform"
242+
#endif
227243

228244
addr2len = sizeof(struct sockaddr_in);
229245
clientfd = accept(sockfd, (struct sockaddr *)&addr2, &addr2len);

0 commit comments

Comments
 (0)