Skip to content

Commit 3e8da39

Browse files
committed
subprocess-posix: use rfork_thread on FreeBSD
1 parent cfcf850 commit 3e8da39

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ features += {'ppoll': cc.has_function('ppoll', args: '-D_GNU_SOURCE',
439439
features += {'memrchr': cc.has_function('memrchr', args: '-D_GNU_SOURCE',
440440
prefix: '#include <string.h>')}
441441
features += {'clone': cc.has_header_symbol('sched.h', 'clone', args: '-D_GNU_SOURCE')}
442+
features += {'rfork': cc.has_header_symbol('unistd.h', 'rfork_thread')}
442443

443444
cd_devices = {
444445
'windows': 'D:',

osdep/subprocess-posix.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static int as_execvpe(const char *path, const char *file, char *const argv[],
8181
return -1;
8282
}
8383

84+
#if !HAVE_RFORK
8485
// In the child process, resets the signal mask to defaults. Also clears any
8586
// signal handlers first so nothing funny happens.
8687
static void reset_signals_child(void)
@@ -94,6 +95,7 @@ static void reset_signals_child(void)
9495
sigemptyset(&sigmask);
9596
sigprocmask(SIG_SETMASK, &sigmask, NULL);
9697
}
98+
#endif
9799

98100
struct child_args {
99101
const char *path;
@@ -122,7 +124,10 @@ static int child_main(void* args)
122124
return 0;
123125
}
124126

127+
// RFSPAWN has reset all signal actions in the child to default
128+
#if !HAVE_RFORK
125129
reset_signals_child();
130+
#endif
126131

127132
for (int n = 0; n < opts->num_fds; n++) {
128133
if (src_fds[n] == opts->fds[n].fd) {
@@ -140,7 +145,7 @@ static int child_main(void* args)
140145
as_execvpe(path, opts->exe, opts->args, opts->env ? opts->env : environ);
141146

142147
child_failed:
143-
#if HAVE_CLONE
148+
#if HAVE_CLONE || HAVE_RFORK
144149
*pipe_end = 1;
145150
#else
146151
(void)write(*pipe_end, &(char){1}, 1); // shouldn't be able to fail
@@ -162,11 +167,16 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
162167
.detach = detach,
163168
};
164169

165-
#if HAVE_CLONE
170+
#if HAVE_CLONE || HAVE_RFORK
166171
const size_t stack_size = 0x8000;
167172
void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
168173
if (stack == MAP_FAILED)
169174
goto done;
175+
#endif
176+
177+
#if HAVE_RFORK
178+
fres = rfork_thread(RFSPAWN, (int8_t*)stack + stack_size, child_main, &child_args);
179+
#elif HAVE_CLONE
170180
fres = clone(child_main, (int8_t*)stack + stack_size, CLONE_VM | CLONE_VFORK | SIGCHLD, &child_args);
171181
#else
172182
int p[2] = {-1, -1};
@@ -192,7 +202,7 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
192202
goto done;
193203
}
194204

195-
#if HAVE_CLONE
205+
#if HAVE_CLONE || HAVE_RFORK
196206
r = child_args.pipe_end;
197207
#else
198208
if (fres == 0) {
@@ -215,7 +225,7 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
215225
}
216226

217227
done:
218-
#if HAVE_CLONE
228+
#if HAVE_CLONE || HAVE_RFORK
219229
munmap(stack, stack_size);
220230
#else
221231
SAFE_CLOSE(p[0]);
@@ -230,14 +240,18 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
230240
static pid_t spawn_process(const char *path, struct mp_subprocess_opts *opts,
231241
int src_fds[])
232242
{
243+
#if !HAVE_RFORK
233244
sigset_t sigmask, oldmask;
234245

235246
sigfillset(&sigmask);
236247
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
248+
#endif
237249

238250
pid_t fres = spawn_process_inner(path, opts, src_fds, opts->detach);
239251

252+
#if !HAVE_RFORK
240253
pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
254+
#endif
241255

242256
return fres;
243257
}

0 commit comments

Comments
 (0)