Blame sysdeps/nptl/fork.c

Packit Service 82fcde
/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#include <libio/libioP.h>
Packit Service 82fcde
#include <tls.h>
Packit Service 82fcde
#include <hp-timing.h>
Packit Service 82fcde
#include <ldsodefs.h>
Packit Service 82fcde
#include <stdio-lock.h>
Packit Service 82fcde
#include <atomic.h>
Packit Service 82fcde
#include <nptl/pthreadP.h>
Packit Service 82fcde
#include <fork.h>
Packit Service 82fcde
#include <arch-fork.h>
Packit Service 82fcde
#include <futex-internal.h>
Packit Service 82fcde
#include <malloc/malloc-internal.h>
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
fresetlockfiles (void)
Packit Service 82fcde
{
Packit Service 82fcde
  _IO_ITER i;
Packit Service 82fcde
Packit Service 82fcde
  for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
Packit Service 82fcde
    if ((_IO_iter_file (i)->_flags & _IO_USER_LOCK) == 0)
Packit Service 82fcde
      _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock));
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
pid_t
Packit Service 82fcde
__libc_fork (void)
Packit Service 82fcde
{
Packit Service 82fcde
  pid_t pid;
Packit Service 82fcde
Packit Service 82fcde
  /* Determine if we are running multiple threads.  We skip some fork
Packit Service 82fcde
     handlers in the single-thread case, to make fork safer to use in
Packit Service 82fcde
     signal handlers.  POSIX requires that fork is async-signal-safe,
Packit Service 82fcde
     but our current fork implementation is not.  */
Packit Service 82fcde
  bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads);
Packit Service 82fcde
Packit Service 82fcde
  __run_fork_handlers (atfork_run_prepare);
Packit Service 82fcde
Packit Service 82fcde
  /* If we are not running multiple threads, we do not have to
Packit Service 82fcde
     preserve lock state.  If fork runs from a signal handler, only
Packit Service 82fcde
     async-signal-safe functions can be used in the child.  These data
Packit Service 82fcde
     structures are only used by unsafe functions, so their state does
Packit Service 82fcde
     not matter if fork was called from a signal handler.  */
Packit Service 82fcde
  if (multiple_threads)
Packit Service 82fcde
    {
Packit Service 82fcde
      _IO_list_lock ();
Packit Service 82fcde
Packit Service 82fcde
      /* Acquire malloc locks.  This needs to come last because fork
Packit Service 82fcde
	 handlers may use malloc, and the libio list lock has an
Packit Service 82fcde
	 indirect malloc dependency as well (via the getdelim
Packit Service 82fcde
	 function).  */
Packit Service 82fcde
      call_function_static_weak (__malloc_fork_lock_parent);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  pid = arch_fork (&THREAD_SELF->tid);
Packit Service 82fcde
Packit Service 82fcde
  if (pid == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct pthread *self = THREAD_SELF;
Packit Service 82fcde
Packit Service 82fcde
      /* See __pthread_once.  */
Packit Service 82fcde
      if (__fork_generation_pointer != NULL)
Packit Service 82fcde
	*__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR;
Packit Service 82fcde
Packit Service 82fcde
#if HP_TIMING_AVAIL
Packit Service 82fcde
      /* The CPU clock of the thread and process have to be set to zero.  */
Packit Service 82fcde
      hp_timing_t now;
Packit Service 82fcde
      HP_TIMING_NOW (now);
Packit Service 82fcde
      THREAD_SETMEM (self, cpuclock_offset, now);
Packit Service 82fcde
      GL(dl_cpuclock_offset) = now;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifdef __NR_set_robust_list
Packit Service 82fcde
      /* Initialize the robust mutex list setting in the kernel which has
Packit Service 82fcde
	 been reset during the fork.  We do not check for errors because if
Packit Service 82fcde
	 it fails here, it must have failed at process startup as well and
Packit Service 82fcde
	 nobody could have used robust mutexes.
Packit Service 82fcde
	 Before we do that, we have to clear the list of robust mutexes
Packit Service 82fcde
	 because we do not inherit ownership of mutexes from the parent.
Packit Service 82fcde
	 We do not have to set self->robust_head.futex_offset since we do
Packit Service 82fcde
	 inherit the correct value from the parent.  We do not need to clear
Packit Service 82fcde
	 the pending operation because it must have been zero when fork was
Packit Service 82fcde
	 called.  */
Packit Service 82fcde
# if __PTHREAD_MUTEX_HAVE_PREV
Packit Service 82fcde
      self->robust_prev = &self->robust_head;
Packit Service 82fcde
# endif
Packit Service 82fcde
      self->robust_head.list = &self->robust_head;
Packit Service 82fcde
# ifdef SHARED
Packit Service 82fcde
      if (__builtin_expect (__libc_pthread_functions_init, 0))
Packit Service 82fcde
	PTHFCT_CALL (ptr_set_robust, (self));
Packit Service 82fcde
# else
Packit Service 82fcde
      extern __typeof (__nptl_set_robust) __nptl_set_robust
Packit Service 82fcde
	__attribute__((weak));
Packit Service 82fcde
      if (__builtin_expect (__nptl_set_robust != NULL, 0))
Packit Service 82fcde
	__nptl_set_robust (self);
Packit Service 82fcde
# endif
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      /* Reset the lock state in the multi-threaded case.  */
Packit Service 82fcde
      if (multiple_threads)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Release malloc locks.  */
Packit Service 82fcde
	  call_function_static_weak (__malloc_fork_unlock_child);
Packit Service 82fcde
Packit Service 82fcde
	  /* Reset the file list.  These are recursive mutexes.  */
Packit Service 82fcde
	  fresetlockfiles ();
Packit Service 82fcde
Packit Service 82fcde
	  /* Reset locks in the I/O code.  */
Packit Service 82fcde
	  _IO_list_resetlock ();
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Reset the lock the dynamic loader uses to protect its data.  */
Packit Service 82fcde
      __rtld_lock_initialize (GL(dl_load_lock));
Packit Service 82fcde
Packit Service 82fcde
      /* Run the handlers registered for the child.  */
Packit Service 82fcde
      __run_fork_handlers (atfork_run_child);
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Release acquired locks in the multi-threaded case.  */
Packit Service 82fcde
      if (multiple_threads)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Release malloc locks, parent process variant.  */
Packit Service 82fcde
	  call_function_static_weak (__malloc_fork_unlock_parent);
Packit Service 82fcde
Packit Service 82fcde
	  /* We execute this even if the 'fork' call failed.  */
Packit Service 82fcde
	  _IO_list_unlock ();
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Run the handlers registered for the parent.  */
Packit Service 82fcde
      __run_fork_handlers (atfork_run_parent);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return pid;
Packit Service 82fcde
}
Packit Service 82fcde
weak_alias (__libc_fork, __fork)
Packit Service 82fcde
libc_hidden_def (__fork)
Packit Service 82fcde
weak_alias (__libc_fork, fork)