View | Details | Raw Unified | Return to bug 16742
Collapse All | Expand All

(-)a/nptl/pthread_atfork.c (-1 / +1 lines)
Lines 53-59 __pthread_atfork (prepare, parent, child) Link Here
53
     void (*parent) (void);
53
     void (*parent) (void);
54
     void (*child) (void);
54
     void (*child) (void);
55
{
55
{
56
  return __register_atfork (prepare, parent, child,
56
  return __register_atfork (prepare, parent, child, __ATFORK_PRIORITY_USER,
57
			    &__dso_handle == NULL ? NULL : __dso_handle);
57
			    &__dso_handle == NULL ? NULL : __dso_handle);
58
}
58
}
59
#ifndef __pthread_atfork
59
#ifndef __pthread_atfork
(-)a/nptl/sysdeps/pthread/bits/libc-lockP.h (+1 lines)
Lines 311-316 __libc_cleanup_routine (struct __pthread_cleanup_frame *f) Link Here
311
extern int __register_atfork (void (*__prepare) (void),
311
extern int __register_atfork (void (*__prepare) (void),
312
			      void (*__parent) (void),
312
			      void (*__parent) (void),
313
			      void (*__child) (void),
313
			      void (*__child) (void),
314
			      int priority,
314
			      void *__dso_handle);
315
			      void *__dso_handle);
315
316
316
/* Functions that are used by this file and are internal to the GNU C
317
/* Functions that are used by this file and are internal to the GNU C
(-)a/nptl/sysdeps/pthread/malloc-machine.h (+2 lines)
Lines 47-52 extern void *__dso_handle __attribute__ ((__weak__)); Link Here
47
  atfork_mem.child_handler = child;					      \
47
  atfork_mem.child_handler = child;					      \
48
  atfork_mem.dso_handle = __dso_handle;					      \
48
  atfork_mem.dso_handle = __dso_handle;					      \
49
  atfork_mem.refcntr = 1;						      \
49
  atfork_mem.refcntr = 1;						      \
50
  atfork_mem.priority = __ATFORK_PRIORITY_MALLOC;                             \
50
  __linkin_atfork (&atfork_mem)
51
  __linkin_atfork (&atfork_mem)
51
#else
52
#else
52
# define thread_atfork(prepare, parent, child) \
53
# define thread_atfork(prepare, parent, child) \
Lines 55-60 extern void *__dso_handle __attribute__ ((__weak__)); Link Here
55
  atfork_mem.child_handler = child;					      \
56
  atfork_mem.child_handler = child;					      \
56
  atfork_mem.dso_handle = &__dso_handle == NULL ? NULL : __dso_handle;	      \
57
  atfork_mem.dso_handle = &__dso_handle == NULL ? NULL : __dso_handle;	      \
57
  atfork_mem.refcntr = 1;						      \
58
  atfork_mem.refcntr = 1;						      \
59
  atfork_mem.priority = __ATFORK_PRIORITY_MALLOC;                             \
58
  __linkin_atfork (&atfork_mem)
60
  __linkin_atfork (&atfork_mem)
59
#endif
61
#endif
60
62
(-)a/nptl/sysdeps/unix/sysv/linux/fork.c (-12 / +29 lines)
Lines 48-53 fresetlockfiles (void) Link Here
48
    _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock));
48
    _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock));
49
}
49
}
50
50
51
static void __fork_lock_IO (void)
52
{
53
  _IO_list_lock ();
54
}
55
56
static void __fork_unlock_IO (void)
57
{
58
  _IO_list_unlock ();
59
}
60
61
static void __fork_reset_IO (void)
62
{
63
  /* Reset the file list.  These are recursive mutexes.  */
64
  fresetlockfiles ();
65
66
  /* Reset locks in the I/O code.  */
67
  _IO_list_resetlock ();
68
}
69
70
void __fork_init (unsigned long *ptr)
71
{
72
  /* Remember the pointer to the generation counter in libpthread.  */
73
  __fork_generation_pointer = ptr;
74
75
  __register_atfork(__fork_lock_IO, __fork_unlock_IO, __fork_reset_IO,
76
		    __ATFORK_PRIORITY_IO, NULL);
77
}
51
78
52
pid_t
79
pid_t
53
__libc_fork (void)
80
__libc_fork (void)
Lines 114-121 __libc_fork (void) Link Here
114
      break;
141
      break;
115
    }
142
    }
116
143
117
  _IO_list_lock ();
118
119
#ifndef NDEBUG
144
#ifndef NDEBUG
120
  pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
145
  pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
121
#endif
146
#endif
Lines 172-183 __libc_fork (void) Link Here
172
# endif
197
# endif
173
#endif
198
#endif
174
199
175
      /* Reset the file list.  These are recursive mutexes.  */
176
      fresetlockfiles ();
177
178
      /* Reset locks in the I/O code.  */
179
      _IO_list_resetlock ();
180
181
      /* Reset the lock the dynamic loader uses to protect its data.  */
200
      /* Reset the lock the dynamic loader uses to protect its data.  */
182
      __rtld_lock_initialize (GL(dl_load_lock));
201
      __rtld_lock_initialize (GL(dl_load_lock));
183
202
Lines 213-222 __libc_fork (void) Link Here
213
      /* Restore the PID value.  */
232
      /* Restore the PID value.  */
214
      THREAD_SETMEM (THREAD_SELF, pid, parentpid);
233
      THREAD_SETMEM (THREAD_SELF, pid, parentpid);
215
234
216
      /* We execute this even if the 'fork' call failed.  */
235
      /* Run the handlers registered for the parent. We execute this
217
      _IO_list_unlock ();
236
	 even if the 'fork' call failed. */
218
219
      /* Run the handlers registered for the parent.  */
220
      while (allp != NULL)
237
      while (allp != NULL)
221
	{
238
	{
222
	  if (allp->handler->parent_handler != NULL)
239
	  if (allp->handler->parent_handler != NULL)
(-)a/nptl/sysdeps/unix/sysv/linux/fork.h (+8 lines)
Lines 34-39 struct fork_handler Link Here
34
  void (*prepare_handler) (void);
34
  void (*prepare_handler) (void);
35
  void (*parent_handler) (void);
35
  void (*parent_handler) (void);
36
  void (*child_handler) (void);
36
  void (*child_handler) (void);
37
  int priority;
37
  void *dso_handle;
38
  void *dso_handle;
38
  unsigned int refcntr;
39
  unsigned int refcntr;
39
  int need_signal;
40
  int need_signal;
Lines 42-57 struct fork_handler Link Here
42
/* The single linked list of all currently registered for handlers.  */
43
/* The single linked list of all currently registered for handlers.  */
43
extern struct fork_handler *__fork_handlers attribute_hidden;
44
extern struct fork_handler *__fork_handlers attribute_hidden;
44
45
46
/* Initialize the multi-threaded fork code. */
47
extern void __fork_init (unsigned long *ptr) attribute_hidden;
45
48
46
/* Function to call to unregister fork handlers.  */
49
/* Function to call to unregister fork handlers.  */
47
extern void __unregister_atfork (void *dso_handle) attribute_hidden;
50
extern void __unregister_atfork (void *dso_handle) attribute_hidden;
48
#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle)
51
#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle)
49
52
53
#define __ATFORK_PRIORITY_USER      0 /* handler might wait for I/O or malloc() */
54
#define __ATFORK_PRIORITY_IO       16 /* handler might wait for malloc(), but will not wait for I/O */
55
#define __ATFORK_PRIORITY_MALLOC   32 /* handler will not wait for malloc() or I/O */
56
50
57
51
/* C library side function to register new fork handlers.  */
58
/* C library side function to register new fork handlers.  */
52
extern int __register_atfork (void (*__prepare) (void),
59
extern int __register_atfork (void (*__prepare) (void),
53
			      void (*__parent) (void),
60
			      void (*__parent) (void),
54
			      void (*__child) (void),
61
			      void (*__child) (void),
62
			      int priority,
55
			      void *dso_handle);
63
			      void *dso_handle);
56
libc_hidden_proto (__register_atfork)
64
libc_hidden_proto (__register_atfork)
57
65
(-)a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c (-3 / +3 lines)
Lines 40-50 __libc_pthread_init (ptr, reclaim, functions) Link Here
40
     void (*reclaim) (void);
40
     void (*reclaim) (void);
41
     const struct pthread_functions *functions;
41
     const struct pthread_functions *functions;
42
{
42
{
43
  /* Remember the pointer to the generation counter in libpthread.  */
43
  /* Initialize the multi-threaded fork code. */
44
  __fork_generation_pointer = ptr;
44
  __fork_init(ptr);
45
45
46
  /* Called by a child after fork.  */
46
  /* Called by a child after fork.  */
47
  __register_atfork (NULL, NULL, reclaim, NULL);
47
  __register_atfork (NULL, NULL, reclaim, __ATFORK_PRIORITY_USER, NULL);
48
48
49
#ifdef SHARED
49
#ifdef SHARED
50
  /* Copy the function pointers into an array in libc.  This enables
50
  /* Copy the function pointers into an array in libc.  This enables
(-)a/nptl/sysdeps/unix/sysv/linux/register-atfork.c (-13 / +36 lines)
Lines 28-34 int __fork_lock = LLL_LOCK_INITIALIZER; Link Here
28
28
29
29
30
/* Number of pre-allocated handler entries.  */
30
/* Number of pre-allocated handler entries.  */
31
#define NHANDLER 48
31
#define NHANDLER 1 //XXX debugging
32
32
33
/* Memory pool for fork handler structures.  */
33
/* Memory pool for fork handler structures.  */
34
static struct fork_handler_pool
34
static struct fork_handler_pool
Lines 43-50 fork_handler_alloc (void) Link Here
43
{
43
{
44
  struct fork_handler_pool *runp = &fork_handler_pool;
44
  struct fork_handler_pool *runp = &fork_handler_pool;
45
  struct fork_handler *result = NULL;
45
  struct fork_handler *result = NULL;
46
  struct fork_handler_pool *next;
46
  unsigned int i;
47
  unsigned int i;
47
48
49
  /* Get the lock to not conflict with other allocations.  */
50
  lll_lock (__fork_lock, LLL_PRIVATE);
51
52
 again:
53
  next = fork_handler_pool.next;
48
  do
54
  do
49
    {
55
    {
50
      /* Search for an empty entry.  */
56
      /* Search for an empty entry.  */
Lines 54-61 fork_handler_alloc (void) Link Here
54
    }
60
    }
55
  while ((runp = runp->next) != NULL);
61
  while ((runp = runp->next) != NULL);
56
62
57
  /* We have to allocate a new entry.  */
63
  /* We have to allocate a new entry. Drop the lock for doing that, since
64
   * our call to calloc() might initialize malloc and cause it to call
65
   * __linkin_atfork. */
66
  lll_unlock (__fork_lock, LLL_PRIVATE);
58
  runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp));
67
  runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp));
68
  lll_lock (__fork_lock, LLL_PRIVATE);
69
70
  if (next != fork_handler_pool.next) {
71
    /* someone allocated a new fork handler pool while we were in
72
     * calloc(). */
73
    free (runp);
74
    goto again;
75
  }
76
59
  if (runp != NULL)
77
  if (runp != NULL)
60
    {
78
    {
61
      /* Enqueue the new memory pool into the list.  */
79
      /* Enqueue the new memory pool into the list.  */
Lines 73-92 fork_handler_alloc (void) Link Here
73
      result->need_signal = 0;
91
      result->need_signal = 0;
74
    }
92
    }
75
93
94
  /* Release the lock.  */
95
  lll_unlock (__fork_lock, LLL_PRIVATE);
96
76
  return result;
97
  return result;
77
}
98
}
78
99
79
100
80
int
101
int
81
__register_atfork (prepare, parent, child, dso_handle)
102
__register_atfork (prepare, parent, child, priority, dso_handle)
82
     void (*prepare) (void);
103
     void (*prepare) (void);
83
     void (*parent) (void);
104
     void (*parent) (void);
84
     void (*child) (void);
105
     void (*child) (void);
106
     int priority;
85
     void *dso_handle;
107
     void *dso_handle;
86
{
108
{
87
  /* Get the lock to not conflict with other allocations.  */
88
  lll_lock (__fork_lock, LLL_PRIVATE);
89
90
  struct fork_handler *newp = fork_handler_alloc ();
109
  struct fork_handler *newp = fork_handler_alloc ();
91
110
92
  if (newp != NULL)
111
  if (newp != NULL)
Lines 95-108 __register_atfork (prepare, parent, child, dso_handle) Link Here
95
      newp->prepare_handler = prepare;
114
      newp->prepare_handler = prepare;
96
      newp->parent_handler = parent;
115
      newp->parent_handler = parent;
97
      newp->child_handler = child;
116
      newp->child_handler = child;
117
      newp->priority = priority;
98
      newp->dso_handle = dso_handle;
118
      newp->dso_handle = dso_handle;
99
119
100
      __linkin_atfork (newp);
120
      __linkin_atfork (newp);
101
    }
121
    }
102
122
103
  /* Release the lock.  */
104
  lll_unlock (__fork_lock, LLL_PRIVATE);
105
106
  return newp == NULL ? ENOMEM : 0;
123
  return newp == NULL ? ENOMEM : 0;
107
}
124
}
108
libc_hidden_def (__register_atfork)
125
libc_hidden_def (__register_atfork)
Lines 112-121 void Link Here
112
attribute_hidden
129
attribute_hidden
113
__linkin_atfork (struct fork_handler *newp)
130
__linkin_atfork (struct fork_handler *newp)
114
{
131
{
115
  do
132
  struct fork_handler **handlerp;
116
    newp->next = __fork_handlers;
133
  lll_lock (__fork_lock, LLL_PRIVATE);
117
  while (catomic_compare_and_exchange_bool_acq (&__fork_handlers,
134
118
						newp, newp->next) != 0);
135
  handlerp = &__fork_handlers;
136
  while (*handlerp && (*handlerp)->priority < newp->priority)
137
    handlerp = &((*handlerp)->next);
138
  newp->next = *handlerp;
139
  *handlerp = newp;
140
141
  lll_unlock (__fork_lock, LLL_PRIVATE);
119
}
142
}
120
143
121
144
(-)a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c (-12 / +1 lines)
Lines 66-86 __unregister_atfork (dso_handle) Link Here
66
     It's a single linked list so readers are.  */
66
     It's a single linked list so readers are.  */
67
  do
67
  do
68
    {
68
    {
69
    again:
70
      if (runp->dso_handle == dso_handle)
69
      if (runp->dso_handle == dso_handle)
71
	{
70
	{
72
	  if (lastp == NULL)
71
	  if (lastp == NULL)
73
	    {
72
	    __fork_handlers = runp->next;
74
	      /* We have to use an atomic operation here because
75
		 __linkin_atfork also uses one.  */
76
	      if (catomic_compare_and_exchange_bool_acq (&__fork_handlers,
77
							 runp->next, runp)
78
		  != 0)
79
		{
80
		  runp = __fork_handlers;
81
		  goto again;
82
		}
83
	    }
84
	  else
73
	  else
85
	    lastp->next = runp->next;
74
	    lastp->next = runp->next;
86
75

Return to bug 16742