fork.c raw

   1  #include <unistd.h>
   2  #include <errno.h>
   3  #include "libc.h"
   4  #include "lock.h"
   5  #include "pthread_impl.h"
   6  #include "fork_impl.h"
   7  
   8  static volatile int *const dummy_lockptr = 0;
   9  
  10  weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
  11  weak_alias(dummy_lockptr, __atexit_lockptr);
  12  weak_alias(dummy_lockptr, __dlerror_lockptr);
  13  weak_alias(dummy_lockptr, __gettext_lockptr);
  14  weak_alias(dummy_lockptr, __locale_lockptr);
  15  weak_alias(dummy_lockptr, __random_lockptr);
  16  weak_alias(dummy_lockptr, __sem_open_lockptr);
  17  weak_alias(dummy_lockptr, __stdio_ofl_lockptr);
  18  weak_alias(dummy_lockptr, __syslog_lockptr);
  19  weak_alias(dummy_lockptr, __timezone_lockptr);
  20  weak_alias(dummy_lockptr, __bump_lockptr);
  21  
  22  weak_alias(dummy_lockptr, __vmlock_lockptr);
  23  
  24  static volatile int *const *const atfork_locks[] = {
  25  	&__at_quick_exit_lockptr,
  26  	&__atexit_lockptr,
  27  	&__dlerror_lockptr,
  28  	&__gettext_lockptr,
  29  	&__locale_lockptr,
  30  	&__random_lockptr,
  31  	&__sem_open_lockptr,
  32  	&__stdio_ofl_lockptr,
  33  	&__syslog_lockptr,
  34  	&__timezone_lockptr,
  35  	&__bump_lockptr,
  36  };
  37  
  38  static void dummy(int x) { }
  39  weak_alias(dummy, __fork_handler);
  40  weak_alias(dummy, __malloc_atfork);
  41  weak_alias(dummy, __ldso_atfork);
  42  
  43  static void dummy_0(void) { }
  44  weak_alias(dummy_0, __tl_lock);
  45  weak_alias(dummy_0, __tl_unlock);
  46  
  47  pid_t fork(void)
  48  {
  49  	sigset_t set;
  50  	__fork_handler(-1);
  51  	__block_app_sigs(&set);
  52  	int need_locks = libc.need_locks > 0;
  53  	if (need_locks) {
  54  		__ldso_atfork(-1);
  55  		__inhibit_ptc();
  56  		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
  57  			if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
  58  		__malloc_atfork(-1);
  59  		__tl_lock();
  60  	}
  61  	pthread_t self=__pthread_self(), next=self->next;
  62  	pid_t ret = _Fork();
  63  	int errno_save = errno;
  64  	if (need_locks) {
  65  		if (!ret) {
  66  			for (pthread_t td=next; td!=self; td=td->next)
  67  				td->tid = -1;
  68  			if (__vmlock_lockptr) {
  69  				__vmlock_lockptr[0] = 0;
  70  				__vmlock_lockptr[1] = 0;
  71  			}
  72  		}
  73  		__tl_unlock();
  74  		__malloc_atfork(!ret);
  75  		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
  76  			if (*atfork_locks[i])
  77  				if (ret) UNLOCK(*atfork_locks[i]);
  78  				else **atfork_locks[i] = 0;
  79  		__release_ptc();
  80  		__ldso_atfork(!ret);
  81  	}
  82  	__restore_sigs(&set);
  83  	__fork_handler(!ret);
  84  	if (ret<0) errno = errno_save;
  85  	return ret;
  86  }
  87