summaryrefslogtreecommitdiff
path: root/src/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc')
-rw-r--r--src/lib/libc/stdlib/abort.c16
-rw-r--r--src/lib/libc/stdlib/atexit.c61
-rw-r--r--src/lib/libc/stdlib/exit.c10
3 files changed, 70 insertions, 17 deletions
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
index 41a9f0f48b..7057f9b1ad 100644
--- a/src/lib/libc/stdlib/abort.c
+++ b/src/lib/libc/stdlib/abort.c
@@ -32,19 +32,19 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: abort.c,v 1.7 2001/08/12 12:03:01 heko Exp $"; 35static char *rcsid = "$OpenBSD: abort.c,v 1.8 2002/09/14 22:03:14 dhartmei Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <signal.h> 38#include <signal.h>
39#include <stdlib.h> 39#include <stdlib.h>
40#include <unistd.h> 40#include <unistd.h>
41#include "thread_private.h" 41#include "thread_private.h"
42 42#include "atexit.h"
43void (*__cleanup)();
44 43
45void 44void
46abort() 45abort()
47{ 46{
47 struct atexit *p = __atexit;
48 static int cleanup_called = 0; 48 static int cleanup_called = 0;
49 sigset_t mask; 49 sigset_t mask;
50 50
@@ -64,9 +64,13 @@ abort()
64 /* 64 /*
65 * POSIX requires we flush stdio buffers on abort 65 * POSIX requires we flush stdio buffers on abort
66 */ 66 */
67 if (cleanup_called == 0 && __cleanup != NULL) { 67 if (cleanup_called == 0) {
68 cleanup_called = 1; 68 while (p != NULL && p->next != NULL)
69 (*__cleanup)(); 69 p = p->next;
70 if (p != NULL && p->fns[0] != NULL) {
71 cleanup_called = 1;
72 (*p->fns[0])();
73 }
70 } 74 }
71 75
72 (void)kill(getpid(), SIGABRT); 76 (void)kill(getpid(), SIGABRT);
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
index da5a0ddda0..98564d0dd3 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -29,7 +29,7 @@
29 */ 29 */
30 30
31#if defined(LIBC_SCCS) && !defined(lint) 31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: atexit.c,v 1.6 2002/09/06 22:48:34 henning Exp $"; 32static char *rcsid = "$OpenBSD: atexit.c,v 1.7 2002/09/14 22:03:14 dhartmei Exp $";
33#endif /* LIBC_SCCS and not lint */ 33#endif /* LIBC_SCCS and not lint */
34 34
35#include <sys/types.h> 35#include <sys/types.h>
@@ -42,6 +42,20 @@ int __atexit_invalid = 1;
42struct atexit *__atexit; 42struct atexit *__atexit;
43 43
44/* 44/*
45 * Function pointers are stored in a linked list of pages. The list
46 * is initially empty, and pages are allocated on demand. The first
47 * function pointer in the first allocated page (the last one in
48 * the linked list) is reserved for the cleanup function.
49 *
50 * Outside the following two functions, all pages are mprotect()'ed
51 * to prevent unintentional/malicious corruption.
52 *
53 * The free(malloc(1)) is a workaround causing malloc_init() to
54 * ensure that malloc.c gets the first mmap() call for its sbrk()
55 * games.
56 */
57
58/*
45 * Register a function to be performed at exit. 59 * Register a function to be performed at exit.
46 */ 60 */
47int 61int
@@ -61,9 +75,6 @@ atexit(fn)
61 } 75 }
62 if (p == NULL) { 76 if (p == NULL) {
63 if (__atexit_invalid) { 77 if (__atexit_invalid) {
64 /* malloc.c wants the first mmap() for sbrk()
65 games ('nice hack'), so enforce
66 malloc_init() with a dummy call. */
67 free(malloc(1)); 78 free(malloc(1));
68 __atexit_invalid = 0; 79 __atexit_invalid = 0;
69 } 80 }
@@ -71,7 +82,11 @@ atexit(fn)
71 MAP_ANON | MAP_PRIVATE, -1, 0); 82 MAP_ANON | MAP_PRIVATE, -1, 0);
72 if (p == MAP_FAILED) 83 if (p == MAP_FAILED)
73 return (-1); 84 return (-1);
74 p->ind = 0; 85 if (__atexit == NULL) {
86 p->fns[0] = NULL;
87 p->ind = 1;
88 } else
89 p->ind = 0;
75 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) / 90 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
76 sizeof(p->fns[0]); 91 sizeof(p->fns[0]);
77 p->next = __atexit; 92 p->next = __atexit;
@@ -82,3 +97,39 @@ atexit(fn)
82 return (-1); 97 return (-1);
83 return (0); 98 return (0);
84} 99}
100
101/*
102 * Register the cleanup function
103 */
104void
105__atexit_register_cleanup(fn)
106 void (*fn)();
107{
108 register struct atexit *p = __atexit;
109 register int pgsize = getpagesize();
110
111 if (pgsize < sizeof(*p))
112 return;
113 while (p != NULL && p->next != NULL)
114 p = p->next;
115 if (p == NULL) {
116 if (__atexit_invalid) {
117 free(malloc(1));
118 __atexit_invalid = 0;
119 }
120 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
121 MAP_ANON | MAP_PRIVATE, -1, 0);
122 if (p == MAP_FAILED)
123 return;
124 p->ind = 1;
125 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
126 sizeof(p->fns[0]);
127 p->next = NULL;
128 __atexit = p;
129 } else {
130 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
131 return;
132 }
133 p->fns[0] = fn;
134 mprotect(p, pgsize, PROT_READ);
135}
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
index c69639125e..e22bd5178e 100644
--- a/src/lib/libc/stdlib/exit.c
+++ b/src/lib/libc/stdlib/exit.c
@@ -32,7 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: exit.c,v 1.7 2002/08/30 07:58:07 dhartmei Exp $"; 35static char *rcsid = "$OpenBSD: exit.c,v 1.8 2002/09/14 22:03:14 dhartmei Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <sys/types.h> 38#include <sys/types.h>
@@ -42,8 +42,6 @@ static char *rcsid = "$OpenBSD: exit.c,v 1.7 2002/08/30 07:58:07 dhartmei Exp $"
42#include "atexit.h" 42#include "atexit.h"
43#include "thread_private.h" 43#include "thread_private.h"
44 44
45void (*__cleanup)();
46
47/* 45/*
48 * This variable is zero until a process has created a thread. 46 * This variable is zero until a process has created a thread.
49 * It is used to avoid calling locking functions in libc when they 47 * It is used to avoid calling locking functions in libc when they
@@ -67,13 +65,13 @@ exit(status)
67 p = __atexit; 65 p = __atexit;
68 while (p != NULL) { 66 while (p != NULL) {
69 for (n = p->ind; --n >= 0;) 67 for (n = p->ind; --n >= 0;)
70 (*p->fns[n])(); 68 if (p->fns[n] != NULL)
69 (*p->fns[n])();
71 q = p; 70 q = p;
72 p = p->next; 71 p = p->next;
73 munmap(q, pgsize); 72 munmap(q, pgsize);
74 } 73 }
75 } 74 }
76 if (__cleanup) 75 /* cleanup, if registered, was called through fns[0] in the last page */
77 (*__cleanup)();
78 _exit(status); 76 _exit(status);
79} 77}