https://bugs.openldap.org/show_bug.cgi?id=9952
Howard Chu hyc@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 Status|UNCONFIRMED |IN_PROGRESS
--- Comment #1 from Howard Chu hyc@openldap.org --- (In reply to artur.zaprzala from comment #0)
A program using libldap will crash on exit after using SSL connection.
The problem is that ldap_int_tls_destroy() is called after the clean up of libssl.
On program exit, at first default_context_int is cleaned up (OPENSSL_cleanup() was registered with atexit()): 0 ossl_lib_ctx_default_deinit () at crypto/context.c:196 1 OPENSSL_cleanup () at crypto/init.c:424 2 OPENSSL_cleanup () at crypto/init.c:338 3 0x00007ffff7873475 in __run_exit_handlers (status=0, listp=0x7ffff7a11658 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:113 4 0x00007ffff78735f0 in __GI_exit (status=<optimized out>) at exit.c:143 5 0x00007ffff785be57 in __libc_start_call_main (main=main@entry=0x55555556aa20 <main>, argc=argc@entry=4, argv=argv@entry=0x7fffffffe2c8) at ../sysdeps/nptl/libc_start_call_main.h:74 6 0x00007ffff785befc in __libc_start_main_impl (main=0x55555556aa20 <main>, argc=4, argv=0x7fffffffe2c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe2b8) at ../csu/libc-start.c:409 7 0x000055555556b575 in _start ()
Then ossl_lib_ctx_get_data() tries to use default_context_int.lock, which is NULL. ldap_int_tls_destroy() is called by ldap_int_destroy_global_options(), registered by "__attribute__ ((destructor))".
It seems that shared library destructors are always called before functions registered with atexit().
Sounds like your description is backwards: the libldap destructor got called after OpenSSL's atexit() handler.
A solution may be to modify libraries/libldap/init.c to use atexit() instead of "__attribute__ ((destructor))". atexit() manual page says: "Since glibc 2.2.3, atexit() can be used within a shared library to establish functions that are called when the shared library is unloaded.".
Functions registered with atexit() are called in the reverse order of their registration, so libssl must by initialized before libldap. If the order is wrong, libldap should detect it somehow and exit with abort().
This sounds OK, since libldap will call OPENSSL_init_ssl() first, we can guarantee that their atexit() invocation happens first.