summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2014-07-10 21:14:23 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2014-07-10 21:14:23 +0000
commit246dc687cb8d8de9afa7524f48e1f06b09a1c153 (patch)
tree3c62288d53d1321ec1e4eb6e9998493b5cb97a18 /lib
parent5cb8b1fc0dea945ecd803eca290106b146179d63 (diff)
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 'lib')
-rw-r--r--lib/libc/stdlib/atexit.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c
index 9b08ebd7e6b..34f76bb7d3a 100644
--- a/lib/libc/stdlib/atexit.c
+++ b/lib/libc/stdlib/atexit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atexit.c,v 1.18 2014/06/18 19:01:10 kettenis Exp $ */
+/* $OpenBSD: atexit.c,v 1.19 2014/07/10 21:14:22 tedu Exp $ */
/*
* Copyright (c) 2002 Daniel Hartmeier
* All rights reserved.
@@ -38,6 +38,7 @@
#include "thread_private.h"
struct atexit *__atexit;
+static int restartloop;
/*
* 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)
fnp->fn_dso = dso;
if (mprotect(p, pgsize, PROT_READ))
goto unlock;
+ restartloop = 1;
ret = 0;
unlock:
_ATEXIT_UNLOCK();
@@ -116,6 +118,8 @@ __cxa_finalize(void *dso)
call_depth++;
+restart:
+ restartloop = 0;
for (p = __atexit; p != NULL; p = p->next) {
for (n = p->ind; --n >= 0;) {
if (p->fns[n].fn_ptr == NULL)
@@ -133,6 +137,8 @@ __cxa_finalize(void *dso)
mprotect(p, pgsize, PROT_READ);
}
(*fn.fn_ptr)(fn.fn_arg);
+ if (restartloop)
+ goto restart;
}
}
@@ -186,6 +192,7 @@ __atexit_register_cleanup(void (*func)(void))
p->fns[0].fn_arg = NULL;
p->fns[0].fn_dso = NULL;
mprotect(p, pgsize, PROT_READ);
+ restartloop = 1;
unlock:
_ATEXIT_UNLOCK();
}