This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Cancelling atexit calls


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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]