Register _cleanup function with atexit
* Register cleanup function with atexit
instead of calling it explicitly on
exit()
* abort() no longer calls _cleanup:
Flushing stdio buffers on abort is no
longer required by POSIX.
* dlmalloc no longer need to reset cleanup
(see above)
* Upstream findfp.c makebuf.c setvbuf.cexit.c
to openbsd versions.
Bug: 14415367
Change-Id: I277058852485a9d3dbb13e5c232db5f9948d78ac
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index b051e22..c607206 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -104,10 +104,10 @@
{
struct atexit *p = __atexit;
struct atexit_fn *fnp;
- int pgsize = getpagesize();
+ size_t pgsize = sysconf(_SC_PAGESIZE);
int ret = -1;
- if (pgsize < (int)sizeof(*p))
+ if (pgsize < sizeof(*p))
return (-1);
_ATEXIT_LOCK();
p = __atexit;
@@ -216,3 +216,41 @@
}
_ATEXIT_UNLOCK();
}
+
+/*
+ * Register the cleanup function
+ */
+void
+__atexit_register_cleanup(void (*func)(void))
+{
+ struct atexit *p;
+ size_t pgsize = sysconf(_SC_PAGESIZE);
+
+ if (pgsize < sizeof(*p))
+ return;
+ _ATEXIT_LOCK();
+ p = __atexit;
+ while (p != NULL && p->next != NULL)
+ p = p->next;
+ if (p == NULL) {
+ p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (p == MAP_FAILED)
+ goto unlock;
+ p->ind = 1;
+ p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
+ sizeof(p->fns[0]);
+ p->next = NULL;
+ __atexit = p;
+ } else {
+ if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
+ goto unlock;
+ }
+ p->fns[0].cxa_func = (void (*)(void*))func;
+ p->fns[0].fn_arg = NULL;
+ p->fns[0].fn_dso = NULL;
+ mprotect(p, pgsize, PROT_READ);
+unlock:
+ _ATEXIT_UNLOCK();
+}
+