Skip to content

Commit dde6fb9

Browse files
committed
subprocess-posix: use rfork_thread on FreeBSD
1 parent f4ca27a commit dde6fb9

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
@@ -464,6 +464,7 @@ features += {'ppoll': cc.has_function('ppoll', args: '-D_GNU_SOURCE',
464464
features += {'memrchr': cc.has_function('memrchr', args: '-D_GNU_SOURCE',
465465
prefix: '#include <string.h>')}
466466
features += {'clone': cc.has_header_symbol('sched.h', 'clone', args: '-D_GNU_SOURCE')}
467+
features += {'rfork': cc.has_header_symbol('unistd.h', 'rfork_thread')}
467468

468469
optical_devices = {
469470
'windows': 'D:',

osdep/subprocess-posix.c

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

78+
#if !HAVE_RFORK
7879
// In the child process, resets the signal mask to defaults. Also clears any
7980
// signal handlers first so nothing funny happens.
8081
static void reset_signals_child(void)
@@ -88,6 +89,7 @@ static void reset_signals_child(void)
8889
sigaction(nr, &sa, NULL);
8990
sigprocmask(SIG_SETMASK, &sigmask, NULL);
9091
}
92+
#endif
9193

9294
struct child_args {
9395
const char *path;
@@ -116,7 +118,10 @@ static int child_main(void* args)
116118
return 0;
117119
}
118120

121+
// RFSPAWN has reset all signal actions in the child to default
122+
#if !HAVE_RFORK
119123
reset_signals_child();
124+
#endif
120125

121126
for (int n = 0; n < opts->num_fds; n++) {
122127
if (src_fds[n] == opts->fds[n].fd) {
@@ -134,7 +139,7 @@ static int child_main(void* args)
134139
as_execvpe(path, opts->exe, opts->args, opts->env ? opts->env : environ);
135140

136141
child_failed:
137-
#if HAVE_CLONE
142+
#if HAVE_CLONE || HAVE_RFORK
138143
*pipe_end = 1;
139144
#else
140145
(void)write(*pipe_end, &(char){1}, 1); // shouldn't be able to fail
@@ -156,11 +161,16 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
156161
.detach = detach,
157162
};
158163

159-
#if HAVE_CLONE
164+
#if HAVE_CLONE || HAVE_RFORK
160165
const size_t stack_size = 0x8000;
161166
void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
162167
if (stack == MAP_FAILED)
163168
goto done;
169+
#endif
170+
171+
#if HAVE_RFORK
172+
fres = rfork_thread(RFSPAWN, (int8_t*)stack + stack_size, child_main, &child_args);
173+
#elif HAVE_CLONE
164174
fres = clone(child_main, (int8_t*)stack + stack_size, CLONE_VM | CLONE_VFORK | SIGCHLD, &child_args);
165175
#else
166176
int p[2] = {-1, -1};
@@ -186,7 +196,7 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
186196
goto done;
187197
}
188198

189-
#if HAVE_CLONE
199+
#if HAVE_CLONE || HAVE_RFORK
190200
r = child_args.pipe_end;
191201
#else
192202
if (fres == 0) {
@@ -209,7 +219,7 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
209219
}
210220

211221
done:
212-
#if HAVE_CLONE
222+
#if HAVE_CLONE || HAVE_RFORK
213223
munmap(stack, stack_size);
214224
#else
215225
SAFE_CLOSE(p[0]);
@@ -224,14 +234,18 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
224234
static pid_t spawn_process(const char *path, struct mp_subprocess_opts *opts,
225235
int src_fds[])
226236
{
237+
#if !HAVE_RFORK
227238
sigset_t sigmask, oldmask;
228239

229240
sigfillset(&sigmask);
230241
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
242+
#endif
231243

232244
pid_t fres = spawn_process_inner(path, opts, src_fds, opts->detach);
233245

246+
#if !HAVE_RFORK
234247
pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
248+
#endif
235249

236250
return fres;
237251
}

0 commit comments

Comments
 (0)