@@ -84,14 +84,14 @@ static NORETURN void die_child(const char *err, va_list params)
8484 unused = write (child_err , "\n" , 1 );
8585 exit (128 );
8686}
87+ #endif
8788
8889static inline void set_cloexec (int fd )
8990{
9091 int flags = fcntl (fd , F_GETFD );
9192 if (flags >= 0 )
9293 fcntl (fd , F_SETFD , flags | FD_CLOEXEC );
9394}
94- #endif
9595
9696static int wait_or_whine (pid_t pid , const char * argv0 , int silent_exec_failure )
9797{
@@ -449,11 +449,35 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
449449 return run_command (& cmd );
450450}
451451
452- #ifdef WIN32
453- static unsigned __stdcall run_thread (void * data )
452+ #ifndef NO_PTHREADS
453+ static pthread_t main_thread ;
454+ static int main_thread_set ;
455+ static pthread_key_t async_key ;
456+
457+ static void * run_thread (void * data )
454458{
455459 struct async * async = data ;
456- return async -> proc (async -> proc_in , async -> proc_out , async -> data );
460+ intptr_t ret ;
461+
462+ pthread_setspecific (async_key , async );
463+ ret = async -> proc (async -> proc_in , async -> proc_out , async -> data );
464+ return (void * )ret ;
465+ }
466+
467+ static NORETURN void die_async (const char * err , va_list params )
468+ {
469+ vreportf ("fatal: " , err , params );
470+
471+ if (!pthread_equal (main_thread , pthread_self ())) {
472+ struct async * async = pthread_getspecific (async_key );
473+ if (async -> proc_in >= 0 )
474+ close (async -> proc_in );
475+ if (async -> proc_out >= 0 )
476+ close (async -> proc_out );
477+ pthread_exit ((void * )128 );
478+ }
479+
480+ exit (128 );
457481}
458482#endif
459483
@@ -499,7 +523,7 @@ int start_async(struct async *async)
499523 else
500524 proc_out = -1 ;
501525
502- #ifndef WIN32
526+ #ifdef NO_PTHREADS
503527 /* Flush stdio before fork() to avoid cloning buffers */
504528 fflush (NULL );
505529
@@ -526,12 +550,29 @@ int start_async(struct async *async)
526550 else if (async -> out )
527551 close (async -> out );
528552#else
553+ if (!main_thread_set ) {
554+ /*
555+ * We assume that the first time that start_async is called
556+ * it is from the main thread.
557+ */
558+ main_thread_set = 1 ;
559+ main_thread = pthread_self ();
560+ pthread_key_create (& async_key , NULL );
561+ set_die_routine (die_async );
562+ }
563+
564+ if (proc_in >= 0 )
565+ set_cloexec (proc_in );
566+ if (proc_out >= 0 )
567+ set_cloexec (proc_out );
529568 async -> proc_in = proc_in ;
530569 async -> proc_out = proc_out ;
531- async -> tid = (HANDLE ) _beginthreadex (NULL , 0 , run_thread , async , 0 , NULL );
532- if (!async -> tid ) {
533- error ("cannot create thread: %s" , strerror (errno ));
534- goto error ;
570+ {
571+ int err = pthread_create (& async -> tid , NULL , run_thread , async );
572+ if (err ) {
573+ error ("cannot create thread: %s" , strerror (err ));
574+ goto error ;
575+ }
535576 }
536577#endif
537578 return 0 ;
@@ -551,17 +592,15 @@ int start_async(struct async *async)
551592
552593int finish_async (struct async * async )
553594{
554- #ifndef WIN32
555- int ret = wait_or_whine (async -> pid , "child process" , 0 );
595+ #ifdef NO_PTHREADS
596+ return wait_or_whine (async -> pid , "child process" , 0 );
556597#else
557- DWORD ret = 0 ;
558- if (WaitForSingleObject (async -> tid , INFINITE ) != WAIT_OBJECT_0 )
559- ret = error ("waiting for thread failed: %lu" , GetLastError ());
560- else if (!GetExitCodeThread (async -> tid , & ret ))
561- ret = error ("cannot get thread exit code: %lu" , GetLastError ());
562- CloseHandle (async -> tid );
598+ void * ret = (void * )(intptr_t )(-1 );
599+
600+ if (pthread_join (async -> tid , & ret ))
601+ error ("pthread_join failed" );
602+ return (int )(intptr_t )ret ;
563603#endif
564- return ret ;
565604}
566605
567606int run_hook (const char * index_file , const char * name , ...)
0 commit comments