diff --git a/contrib/netbsd-tests/lib/libc/stdlib/h_atexit.c b/contrib/netbsd-tests/lib/libc/stdlib/h_atexit.c index b2f91c4c5fe2..d3e1f113abab 100644 --- a/contrib/netbsd-tests/lib/libc/stdlib/h_atexit.c +++ b/contrib/netbsd-tests/lib/libc/stdlib/h_atexit.c @@ -42,9 +42,33 @@ __RCSID("$NetBSD: h_atexit.c,v 1.1 2011/01/12 19:44:08 pgoyette Exp $"); extern int __cxa_atexit(void (*func)(void *), void *, void *); extern void __cxa_finalize(void *); +#if defined(__FreeBSD__) +/* + * On shared object unload, in __cxa_finalize, call and clear all installed + * atexit and __cxa_atexit handlers that are either installed by unloaded + * dso, or points to the functions provided by the dso. + * + * The reason of the change is to ensure that there is no lingering pointers + * to the unloaded code after the dlclose(3). It is known reason for infinite + * stream of the crash reports for many programs which use loadable modules + * and fail to properly clean on module unload. Examples are apache, php, + * perl etc. + * + * You pass the &dso_handle_1 and &dso_handle_2, which points inside the + * main binary, to the registration function. The code from r211706, + * correctly detects that they are for the main binary, and on the first + * call to __cxa_finalize(), which also pass pointer to main binary, all + * registered functions from the main binary are executed. + */ + +static void *dso_handle_1 = (void *)1; +static void *dso_handle_2 = (void *)2; +static void *dso_handle_3 = (void *)3; +#else static int dso_handle_1; static int dso_handle_2; static int dso_handle_3; +#endif static int arg_1; static int arg_2; @@ -167,6 +191,15 @@ main(int argc, char *argv[]) ASSERT(0 == atexit(normal_handler_0)); ASSERT(0 == atexit(normal_handler_1)); +#if defined(__FreeBSD__) + ASSERT(0 == __cxa_atexit(cxa_handler_4, &arg_1, dso_handle_1)); + ASSERT(0 == __cxa_atexit(cxa_handler_5, &arg_1, dso_handle_1)); + ASSERT(0 == __cxa_atexit(cxa_handler_3, &arg_2, dso_handle_2)); + ASSERT(0 == __cxa_atexit(cxa_handler_2, &arg_3, dso_handle_3)); + + __cxa_finalize(dso_handle_1); + __cxa_finalize(dso_handle_2); +#else ASSERT(0 == __cxa_atexit(cxa_handler_4, &arg_1, &dso_handle_1)); ASSERT(0 == __cxa_atexit(cxa_handler_5, &arg_1, &dso_handle_1)); ASSERT(0 == __cxa_atexit(cxa_handler_3, &arg_2, &dso_handle_2)); @@ -174,5 +207,6 @@ main(int argc, char *argv[]) __cxa_finalize(&dso_handle_1); __cxa_finalize(&dso_handle_2); +#endif exit(0); }