Currently, an application can shoot itself in the tail by registering a symbol with atexit and then dlclose-ing the library, which provides the symbol. Programs aren't supposed to that, but sometimes they do -- most notably ImageMagick, which dlopens libjasper, which registers its own clean-up routine with atexit. The proposed patch will make such bugs easier to diagnose -- the ImageMagick problem (crash upon exiting) was mystifying people for years... Fix: The up-to-date version of the patch can be found here: http://aldan.algebra.com/~mi/dlclose-atexit.patch It exposes the __atexit pointer defined in atexit.c and its type and modifies dlclose to scan through all listed functions looking for those, that belong to the object being dlclosed. The method to check whether a symbol belongs to an object is to check, whether the address is between mapbase and mapbase+mapsize of the entry. What could be improved is the addition of a an addr_to_name lookup -- to print the _name_ of the function found to be registered with atexit, rather than merely the function's address.
--- Gordon Stratton <tsr2600@gmail.com> wrote: > I did some testing, and the patch does seem to help. However, there seem > to be a couple cases where a segmentation fault still occurs. The first > is when I attempt to open a file with PHP that does not exist: > > $ php doesntexist > Could not open input file: doesntexist > Segmentation fault > > The second case involves a different PHP extension, pdo_dblib.so (the > OCI8 extensions seem to work OK now): > > (gdb) bt > #0 0x2912313c in ?? () > #1 0x285855c7 in pthread_mutex_lock () from /lib/libc.so.6 > #2 0x28f09bf3 in dbexit () from /usr/local/lib/libsybdb.so.5 > #3 0x28efb86b in zm_shutdown_pdo_dblib () from > /usr/local/lib/php/20060613-debug/pdo_dblib.so > #4 0x0816ceb0 in module_destructor (module=0x832a300) at > /usr/ports/lang/php5/work/php-5.2.3/Zend/zend_API.c:1894 > #5 0x0817171a in zend_hash_apply_deleter (ht=0x826c620, p=0x8330280) > at /usr/ports/lang/php5/work/php-5.2.3/Zend/zend_hash.c:611 > #6 0x08171873 in zend_hash_graceful_reverse_destroy (ht=0x826c620) at > /usr/ports/lang/php5/work/php-5.2.3/Zend/zend_hash.c:646 > #7 0x08166ca7 in zend_shutdown () at > /usr/ports/lang/php5/work/php-5.2.3/Zend/zend.c:733 > #8 0x081205f5 in php_module_shutdown () at > /usr/ports/lang/php5/work/php-5.2.3/main/main.c:1684 > #9 0x081ce73b in main (argc=20, argv=0xbfbfeca0) at > /usr/ports/lang/php5/work/php-5.2.3/sapi/cli/php_cli.c:1333 Have those two cases (doesntexist and pdo_dblib) segfaulted without this patch? ____________________________________________________________________________________ Yahoo! oneSearch: Finally, mobile search that gives answers, not web links. http://mobile.yahoo.com/mobileweb/onesearch?refer=1ONXIC
> On 9/13/07, Simun Mikecin <numisemis@yahoo.com> wrote: > Have those two cases (doesntexist and pdo_dblib) segfaulted without this patch? (CC'ing lists this time, my apologies) doesntexist segfaults without the patch for sure, I can't say for sure about pdo_dblib.. I never _saw_ it but it's possible that other modules were segfaulting first so it never got a chance to segfault. There is at least one case now where PHP does not segfault with the patch where it did before. Gordon
This remains a problem on 8.2 today. multimedia/vlc port always dumps core on exit and the core's stack always contains __cxa_atexit() The patch I submitted with this PR 4 years ago still applies. -mi
Created attachment 153231 [details] Patch Upload the patch so that it's easier to review and doesn't got lost.
For bugs matching the following conditions: - Status == In Progress - Assignee == "bugs@FreeBSD.org" - Last Modified Year <= 2017 Do - Set Status to "Open"
Old discussion here: https://freebsd-arch.freebsd.narkive.com/zzyHX3Bw/dlclose-vs-atexit glibc handles this: Linux notes Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish functions that are called when the shared library is unloaded.
The patch here is interesting but not something that should be committed. A real solution should be committed that prevents a crash. Perhaps making atexit() aware that it is being called from a dso and properly registering that dso in atexit_register(), etc.
*Very naive and untested*. It seems like we need something like this: diff --git lib/libc/stdlib/atexit.c lib/libc/stdlib/atexit.c index bc9ad3ebd7bf..8df6cd4e31b0 100644 --- lib/libc/stdlib/atexit.c +++ lib/libc/stdlib/atexit.c @@ -125,6 +125,8 @@ atexit_register(struct atexit_fn *fptr) return 0; } +extern void *__dso_handle __hidden; + /* * Register a function to be performed at exit. */ @@ -137,7 +139,7 @@ atexit(void (*func)(void)) fn.fn_type = ATEXIT_FN_STD; fn.fn_ptr.std_func = func; fn.fn_arg = NULL; - fn.fn_dso = NULL; + fn.fn_dso = __dso_handle; error = atexit_register(&fn); return (error);