]> git.ipfire.org Git - thirdparty/glibc.git/blob - htl/register-atfork.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / htl / register-atfork.c
1 /* Atfork handling. Hurd pthread version.
2 Copyright (C) 2002-2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <errno.h>
20 #include <stdlib.h>
21 #include <libc-lock.h>
22 #include <fork.h>
23
24 struct atfork
25 {
26 void (*prepare) (void);
27 void (*parent) (void);
28 void (*child) (void);
29 void *dso_handle;
30 struct atfork *prev;
31 struct atfork *next;
32 };
33
34 /* TODO: better locking */
35 __libc_lock_define_initialized (static, atfork_lock);
36 static struct atfork *fork_handlers, *fork_last_handler;
37
38 static void
39 atfork_pthread_prepare (void)
40 {
41 struct atfork *handlers, *last_handler;
42
43 __libc_lock_lock (atfork_lock);
44 handlers = fork_handlers;
45 last_handler = fork_last_handler;
46 __libc_lock_unlock (atfork_lock);
47
48 if (last_handler == NULL)
49 return;
50
51 while (1)
52 {
53 if (last_handler->prepare != NULL)
54 last_handler->prepare ();
55 if (last_handler == handlers)
56 break;
57 last_handler = last_handler->prev;
58 }
59 }
60 text_set_element (_hurd_atfork_prepare_hook, atfork_pthread_prepare);
61
62 static void
63 atfork_pthread_parent (void)
64 {
65 struct atfork *handlers;
66
67 __libc_lock_lock (atfork_lock);
68 handlers = fork_handlers;
69 __libc_lock_unlock (atfork_lock);
70
71 while (handlers != NULL)
72 {
73 if (handlers->parent != NULL)
74 handlers->parent ();
75 handlers = handlers->next;
76 }
77 }
78 text_set_element (_hurd_atfork_parent_hook, atfork_pthread_parent);
79
80 static void
81 atfork_pthread_child (void)
82 {
83 struct atfork *handlers;
84
85 __libc_lock_lock (atfork_lock);
86 handlers = fork_handlers;
87 __libc_lock_unlock (atfork_lock);
88
89 while (handlers != NULL)
90 {
91 if (handlers->child != NULL)
92 handlers->child ();
93 handlers = handlers->next;
94 }
95 }
96 text_set_element (_hurd_atfork_child_hook, atfork_pthread_child);
97
98 int
99 __register_atfork (void (*prepare) (void),
100 void (*parent) (void),
101 void (*child) (void),
102 void *dso_handle)
103 {
104 struct atfork *new = malloc (sizeof (*new));
105 if (new == NULL)
106 return errno;
107
108 new->prepare = prepare;
109 new->parent = parent;
110 new->child = child;
111 new->dso_handle = dso_handle;
112 new->next = NULL;
113
114 __libc_lock_lock (atfork_lock);
115 new->prev = fork_last_handler;
116 if (fork_last_handler != NULL)
117 fork_last_handler->next = new;
118 if (fork_handlers == NULL)
119 fork_handlers = new;
120 fork_last_handler = new;
121 __libc_lock_unlock (atfork_lock);
122
123 return 0;
124 }
125 libc_hidden_def (__register_atfork)
126
127 void
128 __unregister_atfork (void *dso_handle)
129 {
130 struct atfork **handlers, *prev = NULL, *next;
131 __libc_lock_lock (atfork_lock);
132 handlers = &fork_handlers;
133 while (*handlers != NULL)
134 {
135 if ((*handlers)->dso_handle == dso_handle)
136 {
137 /* Drop this handler from the list. */
138 if (*handlers == fork_last_handler)
139 {
140 /* Was last, new last is prev, if any. */
141 fork_last_handler = prev;
142 }
143
144 next = (*handlers)->next;
145 if (next != NULL)
146 next->prev = prev;
147 *handlers = next;
148 }
149 else
150 {
151 /* Just proceed to next handler. */
152 prev = *handlers;
153 handlers = &prev->next;
154 }
155 }
156 __libc_lock_unlock (atfork_lock);
157 }