]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/unregister-atfork.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl / unregister-atfork.c
CommitLineData
bfff8b1b 1/* Copyright (C) 2002-2017 Free Software Foundation, Inc.
76a50749
UD
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
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
76a50749
UD
18
19#include <errno.h>
20#include <stdlib.h>
8dea90aa 21#include <fork.h>
92d83c72 22#include <atomic.h>
a2f0363f 23#include <futex-internal.h>
4e648ea3
UD
24
25
76a50749 26void
9d46370c 27__unregister_atfork (void *dso_handle)
76a50749 28{
92d83c72
UD
29 /* Check whether there is any entry in the list which we have to
30 remove. It is likely that this is not the case so don't bother
31 getting the lock.
32
33 We do not worry about other threads adding entries for this DSO
34 right this moment. If this happens this is a race and we can do
35 whatever we please. The program will crash anyway seen. */
36 struct fork_handler *runp = __fork_handlers;
37 struct fork_handler *lastp = NULL;
38
39 while (runp != NULL)
40 if (runp->dso_handle == dso_handle)
41 break;
42 else
dfdd294a 43 {
92d83c72
UD
44 lastp = runp;
45 runp = runp->next;
dfdd294a 46 }
76a50749 47
92d83c72
UD
48 if (runp == NULL)
49 /* Nothing to do. */
50 return;
dfdd294a 51
92d83c72
UD
52 /* Get the lock to not conflict with additions or deletions. Note
53 that there couldn't have been another thread deleting something.
54 The __unregister_atfork function is only called from the
55 dlclose() code which itself serializes the operations. */
e51deae7 56 lll_lock (__fork_lock, LLL_PRIVATE);
dfdd294a 57
92d83c72
UD
58 /* We have to create a new list with all the entries we don't remove. */
59 struct deleted_handler
60 {
61 struct fork_handler *handler;
62 struct deleted_handler *next;
63 } *deleted = NULL;
64
65 /* Remove the entries for the DSO which is unloaded from the list.
66 It's a single linked list so readers are. */
67 do
68 {
ad3371fb 69 again:
92d83c72
UD
70 if (runp->dso_handle == dso_handle)
71 {
72 if (lastp == NULL)
ad3371fb
UD
73 {
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 }
92d83c72
UD
84 else
85 lastp->next = runp->next;
86
87 /* We cannot overwrite the ->next element now. Put the deleted
88 entries in a separate list. */
89 struct deleted_handler *newp = alloca (sizeof (*newp));
90 newp->handler = runp;
91 newp->next = deleted;
92 deleted = newp;
93 }
94 else
95 lastp = runp;
96
97 runp = runp->next;
98 }
99 while (runp != NULL);
76a50749
UD
100
101 /* Release the lock. */
e51deae7 102 lll_unlock (__fork_lock, LLL_PRIVATE);
92d83c72
UD
103
104 /* Walk the list of all entries which have to be deleted. */
105 while (deleted != NULL)
106 {
107 /* We need to be informed by possible current users. */
108 deleted->handler->need_signal = 1;
109 /* Make sure this gets written out first. */
110 atomic_write_barrier ();
111
112 /* Decrement the reference counter. If it does not reach zero
113 wait for the last user. */
114 atomic_decrement (&deleted->handler->refcntr);
115 unsigned int val;
116 while ((val = deleted->handler->refcntr) != 0)
a2f0363f 117 futex_wait_simple (&deleted->handler->refcntr, val, FUTEX_PRIVATE);
92d83c72
UD
118
119 deleted = deleted->next;
120 }
76a50749 121}