diff options
author | tedu <> | 2014-07-10 21:14:22 +0000 |
---|---|---|
committer | tedu <> | 2014-07-10 21:14:22 +0000 |
commit | 7f6a95d90665644779afb040180fa14a6bd15a15 (patch) | |
tree | 363d9818bba92cf877e4b7765f26becc6d0ed8e7 /src | |
parent | bbf0836e37dbf8c0b3a354c7df445b5f0fcf6f1a (diff) | |
download | openbsd-7f6a95d90665644779afb040180fa14a6bd15a15.tar.gz openbsd-7f6a95d90665644779afb040180fa14a6bd15a15.tar.bz2 openbsd-7f6a95d90665644779afb040180fa14a6bd15a15.zip |
as noted by google/android via kettenis, atexit handlers can install new
handlers. if this happens, restart the loop.
ok kettenis matthew millert miod
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/atexit.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c index 9b08ebd7e6..34f76bb7d3 100644 --- a/src/lib/libc/stdlib/atexit.c +++ b/src/lib/libc/stdlib/atexit.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: atexit.c,v 1.18 2014/06/18 19:01:10 kettenis Exp $ */ | 1 | /* $OpenBSD: atexit.c,v 1.19 2014/07/10 21:14:22 tedu Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002 Daniel Hartmeier | 3 | * Copyright (c) 2002 Daniel Hartmeier |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -38,6 +38,7 @@ | |||
38 | #include "thread_private.h" | 38 | #include "thread_private.h" |
39 | 39 | ||
40 | struct atexit *__atexit; | 40 | struct atexit *__atexit; |
41 | static int restartloop; | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Function pointers are stored in a linked list of pages. The list | 44 | * Function pointers are stored in a linked list of pages. The list |
@@ -95,6 +96,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso) | |||
95 | fnp->fn_dso = dso; | 96 | fnp->fn_dso = dso; |
96 | if (mprotect(p, pgsize, PROT_READ)) | 97 | if (mprotect(p, pgsize, PROT_READ)) |
97 | goto unlock; | 98 | goto unlock; |
99 | restartloop = 1; | ||
98 | ret = 0; | 100 | ret = 0; |
99 | unlock: | 101 | unlock: |
100 | _ATEXIT_UNLOCK(); | 102 | _ATEXIT_UNLOCK(); |
@@ -116,6 +118,8 @@ __cxa_finalize(void *dso) | |||
116 | 118 | ||
117 | call_depth++; | 119 | call_depth++; |
118 | 120 | ||
121 | restart: | ||
122 | restartloop = 0; | ||
119 | for (p = __atexit; p != NULL; p = p->next) { | 123 | for (p = __atexit; p != NULL; p = p->next) { |
120 | for (n = p->ind; --n >= 0;) { | 124 | for (n = p->ind; --n >= 0;) { |
121 | if (p->fns[n].fn_ptr == NULL) | 125 | if (p->fns[n].fn_ptr == NULL) |
@@ -133,6 +137,8 @@ __cxa_finalize(void *dso) | |||
133 | mprotect(p, pgsize, PROT_READ); | 137 | mprotect(p, pgsize, PROT_READ); |
134 | } | 138 | } |
135 | (*fn.fn_ptr)(fn.fn_arg); | 139 | (*fn.fn_ptr)(fn.fn_arg); |
140 | if (restartloop) | ||
141 | goto restart; | ||
136 | } | 142 | } |
137 | } | 143 | } |
138 | 144 | ||
@@ -186,6 +192,7 @@ __atexit_register_cleanup(void (*func)(void)) | |||
186 | p->fns[0].fn_arg = NULL; | 192 | p->fns[0].fn_arg = NULL; |
187 | p->fns[0].fn_dso = NULL; | 193 | p->fns[0].fn_dso = NULL; |
188 | mprotect(p, pgsize, PROT_READ); | 194 | mprotect(p, pgsize, PROT_READ); |
195 | restartloop = 1; | ||
189 | unlock: | 196 | unlock: |
190 | _ATEXIT_UNLOCK(); | 197 | _ATEXIT_UNLOCK(); |
191 | } | 198 | } |