@@ -34,7 +34,6 @@ extern char **environ;
3434
3535#if HAVE_CLONE
3636#include <sched.h>
37- #include <sys/mman.h>
3837#endif
3938
4039#ifdef SIGRTMAX
@@ -95,25 +94,27 @@ struct child_args {
9594 const char * path ;
9695 struct mp_subprocess_opts * opts ;
9796 int * src_fds ;
97+ void * child_stack ;
9898 int pipe_end ;
9999 bool detach ;
100100};
101101
102102static pid_t spawn_process_inner (const char * path , struct mp_subprocess_opts * opts ,
103- int src_fds [], bool detach );
103+ int src_fds [], bool detach , void * stacks [] );
104104
105105static int child_main (void * args )
106106{
107107 struct child_args * child_args = args ;
108108 const char * path = child_args -> path ;
109109 struct mp_subprocess_opts * opts = child_args -> opts ;
110110 int * src_fds = child_args -> src_fds ;
111+ void * child_stack = child_args -> child_stack ;
111112 int * pipe_end = & child_args -> pipe_end ;
112113 bool detach = child_args -> detach ;
113114
114115 if (detach ) {
115116 setsid ();
116- if (!spawn_process_inner (path , opts , src_fds , false))
117+ if (!spawn_process_inner (path , opts , src_fds , false, & child_stack ))
117118 goto child_failed ;
118119 return 0 ;
119120 }
@@ -148,7 +149,7 @@ static int child_main(void* args)
148149}
149150
150151static pid_t spawn_process_inner (const char * path , struct mp_subprocess_opts * opts ,
151- int src_fds [], bool detach )
152+ int src_fds [], bool detach , void * stacks [] )
152153{
153154 pid_t fres = 0 ;
154155 int r ;
@@ -157,21 +158,15 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
157158 .path = path ,
158159 .opts = opts ,
159160 .src_fds = src_fds ,
161+ .child_stack = stacks [1 ],
160162 .pipe_end = 0 ,
161163 .detach = detach ,
162164 };
163165
164- #if HAVE_CLONE || HAVE_RFORK
165- const size_t stack_size = 0x8000 ;
166- void * stack = mmap (NULL , stack_size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK , -1 , 0 );
167- if (stack == MAP_FAILED )
168- goto done ;
169- #endif
170-
171166#if HAVE_RFORK
172- fres = rfork_thread (RFSPAWN , ( int8_t * ) stack + stack_size , child_main , & child_args );
167+ fres = rfork_thread (RFSPAWN , stacks [ 0 ] , child_main , & child_args );
173168#elif HAVE_CLONE
174- fres = clone (child_main , ( int8_t * ) stack + stack_size , CLONE_VM | CLONE_VFORK | SIGCHLD , & child_args );
169+ fres = clone (child_main , stacks [ 0 ] , CLONE_VM | CLONE_VFORK | SIGCHLD , & child_args );
175170#else
176171 int p [2 ] = {-1 , -1 };
177172 // We setup a communication pipe to signal failure. Since the child calls
@@ -219,9 +214,7 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
219214 }
220215
221216done :
222- #if HAVE_CLONE || HAVE_RFORK
223- munmap (stack , stack_size );
224- #else
217+ #if !HAVE_CLONE && !HAVE_RFORK
225218 SAFE_CLOSE (p [0 ]);
226219 SAFE_CLOSE (p [1 ]);
227220#endif
@@ -234,19 +227,35 @@ static pid_t spawn_process_inner(const char *path, struct mp_subprocess_opts *op
234227static pid_t spawn_process (const char * path , struct mp_subprocess_opts * opts ,
235228 int src_fds [])
236229{
230+ bool detach = opts -> detach ;
231+ void * stacks [2 ];
232+
233+ #if HAVE_CLONE || HAVE_RFORK
234+ // pre-allocate stacks so we can be async-signal-safe in spawn_process_inner()
235+ const size_t stack_size = 0x8000 ;
236+ void * ctx = talloc_new (NULL );
237+ // stack should be aligned to 16 bytes, which is guaranteed by malloc
238+ stacks [0 ] = (int8_t * )talloc_size (ctx , stack_size ) + stack_size ;
239+ if (detach ) stacks [1 ] = (int8_t * )talloc_size (ctx , stack_size ) + stack_size ;
240+ #endif
241+
237242#if !HAVE_RFORK
238243 sigset_t sigmask , oldmask ;
239244
240245 sigfillset (& sigmask );
241246 pthread_sigmask (SIG_BLOCK , & sigmask , & oldmask );
242247#endif
243248
244- pid_t fres = spawn_process_inner (path , opts , src_fds , opts -> detach );
249+ pid_t fres = spawn_process_inner (path , opts , src_fds , detach , stacks );
245250
246251#if !HAVE_RFORK
247252 pthread_sigmask (SIG_SETMASK , & oldmask , NULL );
248253#endif
249254
255+ #if HAVE_CLONE || HAVE_RFORK
256+ talloc_free (ctx );
257+ #endif
258+
250259 return fres ;
251260}
252261
0 commit comments