This is the mail archive of the
libc-alpha@cygnus.com
mailing list for the glibc project.
Cancelling atexit calls
- To: libc-alpha@gnu.org, egcs-patches@cygnus.com
- Subject: Cancelling atexit calls
- From: Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>
- Date: Sun, 6 Sep 1998 12:03:23 +0200
This is a proposal for an atexit interface where atexit functions can
be run or removed before exit is called.
A primary application for this interface is the registration of
destructors in C++, so I send it both to libc-alpha, and egcs-patches.
The source changes are relative to glibc 2.0.95.
Three new _GNU_SOURCE functions are proposed:
/* Register a function that can be unregistered. */
extern int atexitc __P ((void (*__func) (void), void *__token));
/* Run all functions registered on the same token. */
extern int run_atexit __P ((void *__token));
/* Cancel all functions registered on the same token. */
extern int cancel_atexit __P ((void *__token));
On systems with atexitc() available, g++ will register destructor
functions with a token specific to the shared library (perhaps, the
token is the object that needs to be destroyed). When the library is
dlclosed, a call to run_atexit() will execute all destructors
registered from that library. When exit() is called later, the atexit
processing will not attempt to access the shared library anymore.
There is a specific problem what token to chose: I've tried using
&_end, since the linker appears to set this to the end of each shared
image. At run-time, I notice that all shared libraries have the same
value for _end (on i486-pc-linux-gnu). Is this a linker bug? Ideally,
I'd like to use a technique similar to _GLOBAL_OFFSET_TABLE_.
If that fails, it is still possible to cancel each destructor
separately.
Any comments appreciated,
Martin
1998-09-06 Martin von Löwis <loewis@informatik.hu-berlin.de>
* stdlib/atexitc.c: New file.
* stdlib/run_atexit.c: New file.
* stdlib/cancel_atexit.c: New file.
* stdlib/Makefile: Add them.
* stdlib/stdlib.h (atexitc, run_atexit, cancel_atexit): New
functions.
* stdlib/Versions [GLIBC_2.1]: Add them.
* stdlib/exit.h (enum flavor): New value ef_atc.
(union func): New variant atc.
* stdlib/exit.c (exit): Call atc functions.
diff -uN glibc-2.0.95/stdlib/Makefile /usr/src1/glibc-2.0.95/stdlib/Makefile
--- glibc-2.0.95/stdlib/Makefile Fri Jun 26 22:21:17 1998
+++ /usr/src1/glibc-2.0.95/stdlib/Makefile Sat Sep 5 08:32:26 1998
@@ -29,7 +29,7 @@
abort \
bsearch qsort msort \
getenv putenv setenv secure-getenv \
- exit on_exit atexit \
+ exit on_exit atexit atexitc run_atexit cancel_atexit \
abs labs llabs \
div ldiv lldiv \
mblen mbstowcs mbtowc wcstombs wctomb \
diff -uN glibc-2.0.95/stdlib/Versions /usr/src1/glibc-2.0.95/stdlib/Versions
--- glibc-2.0.95/stdlib/Versions Thu Jul 2 19:47:53 1998
+++ /usr/src1/glibc-2.0.95/stdlib/Versions Sat Sep 5 08:34:55 1998
@@ -69,7 +69,10 @@
}
GLIBC_2.1 {
# a*
- addseverity;
+ addseverity; atexitc;
+
+ # c*
+ cancel_atexit;
# f*
fmtmsg;
@@ -79,6 +82,9 @@
# m*
makecontext;
+
+ # r*
+ run_atexit;
# s*
strtoimax; strtoumax; swapcontext;
diff -uN glibc-2.0.95/stdlib/atexitc.c /usr/src1/glibc-2.0.95/stdlib/atexitc.c
--- glibc-2.0.95/stdlib/atexitc.c Thu Jan 1 01:00:00 1970
+++ /usr/src1/glibc-2.0.95/stdlib/atexitc.c Sat Sep 5 08:34:01 1998
@@ -0,0 +1,36 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include "exit.h"
+
+/* Register a function to be called by exit. */
+int
+__atexitc (void (*func) (), void *token)
+{
+ struct exit_function *new = __new_exitfn ();
+
+ if (new == NULL)
+ return -1;
+
+ new->flavor = ef_atc;
+ new->func.atc.fn = func;
+ new->func.atc.token = token;
+ return 0;
+}
+weak_alias (__atexitc, atexitc)
diff -uN glibc-2.0.95/stdlib/cancel_atexit.c /usr/src1/glibc-2.0.95/stdlib/cancel_atexit.c
--- glibc-2.0.95/stdlib/cancel_atexit.c Thu Jan 1 01:00:00 1970
+++ /usr/src1/glibc-2.0.95/stdlib/cancel_atexit.c Sat Sep 5 10:42:34 1998
@@ -0,0 +1,42 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include "exit.h"
+
+/* Cancel all atc functions registered with token. */
+int
+__cancel_atexit (void *token)
+{
+ struct exit_function_list * func;
+ for (func = __exit_funcs; func; func = func->next)
+ {
+ int i;
+ for (i = func->idx - 1; i >= 0; i--)
+ {
+ const struct exit_function *const f = func->fns + i;
+ if (f->flavor == ef_atc && f->func.atc.token == token)
+ {
+ /* FIXME: need locking for modification? */
+ f->flavor = ef_us;
+ }
+ }
+ }
+ return 0;
+}
+weak_alias (__cancel_atexit, cancel_atexit)
diff -uN glibc-2.0.95/stdlib/exit.c /usr/src1/glibc-2.0.95/stdlib/exit.c
--- glibc-2.0.95/stdlib/exit.c Wed Nov 12 00:33:20 1997
+++ /usr/src1/glibc-2.0.95/stdlib/exit.c Thu Sep 3 08:12:52 1998
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -53,6 +53,9 @@
break;
case ef_at:
(*f->func.at) ();
+ break;
+ case ef_atc:
+ (*f->func.atc.fn) ();
break;
}
}
diff -uN glibc-2.0.95/stdlib/exit.h /usr/src1/glibc-2.0.95/stdlib/exit.h
--- glibc-2.0.95/stdlib/exit.h Sat Jun 21 04:24:26 1997
+++ /usr/src1/glibc-2.0.95/stdlib/exit.h Thu Sep 3 08:13:21 1998
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,7 +21,7 @@
struct exit_function
{
- enum { ef_free, ef_us, ef_on, ef_at } flavor; /* `ef_free' MUST be zero! */
+ enum { ef_free, ef_us, ef_on, ef_at, ef_atc } flavor; /* `ef_free' MUST be zero! */
union
{
void (*at) (void);
@@ -30,6 +30,11 @@
void (*fn) (int status, void *arg);
void *arg;
} on;
+ struct
+ {
+ void (*fn) (void);
+ void *token;
+ } atc;
} func;
};
struct exit_function_list
diff -uN glibc-2.0.95/stdlib/run_atexit.c /usr/src1/glibc-2.0.95/stdlib/run_atexit.c
--- glibc-2.0.95/stdlib/run_atexit.c Thu Jan 1 01:00:00 1970
+++ /usr/src1/glibc-2.0.95/stdlib/run_atexit.c Sat Sep 5 10:42:18 1998
@@ -0,0 +1,43 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <stdlib.h>
+#include "exit.h"
+
+/* Run all atc functions registered with token. */
+int
+__run_atexit (void *token)
+{
+ struct exit_function_list * func;
+ for (func = __exit_funcs; func; func = func->next)
+ {
+ int i;
+ for (i = func->idx - 1; i >= 0; i--)
+ {
+ const struct exit_function *const f = func->fns + i;
+ if (f->flavor == ef_atc && f->func.atc.token == token)
+ {
+ (*f->func.atc.fn) ();
+ /* FIXME: need locking for modification? */
+ f->flavor = ef_us;
+ }
+ }
+ }
+ return 0;
+}
+weak_alias (__run_atexit, run_atexit)
diff -uN glibc-2.0.95/stdlib/stdlib.h /usr/src1/glibc-2.0.95/stdlib/stdlib.h
--- glibc-2.0.95/stdlib/stdlib.h Wed Jul 8 20:09:07 1998
+++ /usr/src1/glibc-2.0.95/stdlib/stdlib.h Sat Sep 5 08:34:31 1998
@@ -510,6 +510,18 @@
__ptr_t __arg));
#endif
+#ifdef __USE_GNU
+/* Register a function that can be unregistered. */
+extern int __atexitc __P ((void (*__func) (void), void *__token));
+extern int atexitc __P ((void (*__func) (void), void *__token));
+/* Run all functions registered on the same token. */
+extern int __run_atexit __P ((void *__token));
+extern int run_atexit __P ((void *__token));
+/* Cancel all functions registered on the same token. */
+extern int __cancel_atexit __P ((void *__token));
+extern int cancel_atexit __P ((void *__token));
+#endif
+
/* Call all functions registered with `atexit' and `on_exit',
in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */