ef70dde8a2849cc5bdfc6d17cc0a469ee5a2e12e
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / register-atfork.c
1 /* Copyright (C) 2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <stdlib.h>
22 #include "fork.h"
23
24
25 int
26 __register_atfork (prepare, parent, child, dso_handle)
27      void (*prepare) (void);
28      void (*parent) (void);
29      void (*child) (void);
30      void *dso_handle;
31 {
32   struct fork_handler *new_prepare = NULL;
33   struct fork_handler *new_parent = NULL;
34   struct fork_handler *new_child = NULL;
35
36   if (prepare != NULL)
37     {
38       new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare));
39       if (new_prepare == NULL)
40         goto out1;
41
42       new_prepare->handler = prepare;
43       new_prepare->dso_handle = dso_handle;
44     }
45
46   if (parent != NULL)
47     {
48       new_parent = (struct fork_handler *) malloc (sizeof (*new_parent));
49       if (new_parent == NULL)
50         goto out2;
51
52       new_parent->handler = parent;
53       new_parent->dso_handle = dso_handle;
54     }
55
56   if (child != NULL)
57     {
58       new_child = (struct fork_handler *) malloc (sizeof (*new_child));
59       if (new_child == NULL)
60         {
61           free (new_parent);
62         out2:
63           free (new_prepare);
64         out1:
65           return errno;
66         }
67
68       new_child->handler = child;
69       new_child->dso_handle = dso_handle;
70     }
71
72   /* Get the lock to not conflict with running forks.  */
73   lll_lock (__fork_lock);
74
75   /* Now that we have all the handlers allocate enqueue them.  */
76   if (new_prepare != NULL)
77     list_add_tail (&new_prepare->list, &__fork_prepare_list);
78   if (new_parent != NULL)
79     list_add_tail (&new_parent->list, &__fork_parent_list);
80   if (new_child != NULL)
81     list_add_tail (&new_child->list, &__fork_child_list);
82
83   /* Release the lock.  */
84   lll_unlock (__fork_lock);
85
86   return 0;
87 }