threads/135477: dlclose on shared object liked with libthr causes SIGSEGV

Jacques Caron jc at oxado.com
Thu Jun 11 13:20:01 UTC 2009


>Number:         135477
>Category:       threads
>Synopsis:       dlclose on shared object liked with libthr causes SIGSEGV
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-threads
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jun 11 13:20:00 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Jacques Caron
>Release:        7.1
>Organization:
Oxado
>Environment:
FreeBSD DSVR009130.naxopay.com 7.1-STABLE FreeBSD 7.1-STABLE #0: Thu Jan 29 19:14:58 GMT 2009     jc at DSVR009130.naxopay.com:/usr/src/sys/i386/compile/CARP  i386
>Description:
When an application not linked with libthr dynamically loads a shared object linked with libthr (directly or indirectly), some libc stubs are replaced by their libthr equivalents.

When the application unloads the same object, libthr is unloaded as well, but links towards libthr functions are left in place, which results in a crash as soon as those functions are called (often implicitly, by thread-protected functions in libc, e.g. gethostbyname).

This happens for instance with apache 1.3 modules that are linked with a thread-enabled version of the postgresql client library (libpq). Restarting the server will quite often cause a crash.
>How-To-Repeat:
#!/bin/sh

cat <<EOF >test_load_module.c
#include <netdb.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc,char **argv)
{
        void * handle;

        if (argc!=2)
        {
                printf("usage %s <module_to_load>\n", argv[0]);
                return -1;
        }
        handle  =       dlopen(argv[1], RTLD_NOW);
        if (!handle)
        {
                printf("dlopen: %s\n",dlerror());
                return -1;
        }
        gethostbyname("127.0.0.1");
        dlclose(handle);
        gethostbyname("127.0.0.1");
        printf("Everything went fine!\n");

        return 0;
}
EOF

cat <<EOF >test_module.c
void dummy(void)
{
}
EOF

cc -g -Wall -fpic -c test_module.c -o test_module.o
cc -g -shared test_module.o -o test_module_no_thr.so
cc -g -shared test_module.o -lthr -o test_module_thr.so

cc -g -Wall test_load_module.c -o test_load_module_no_thr
cc -g -Wall test_load_module.c -lthr -o test_load_module_thr

echo "Main program no thr, module no thr"
./test_load_module_no_thr ./test_module_no_thr.so
echo "Main program no thr, module thr"
./test_load_module_no_thr ./test_module_thr.so
echo "Main program thr, module no thr"
./test_load_module_thr ./test_module_no_thr.so
echo "Main program thr, module thr"
./test_load_module_thr ./test_module_thr.so

>Fix:
A workaround is to build the loading application with -lthr even if threads are not needed (this way libthr is not unloaded when the module is unloaded), or make sure that no loaded modules are linked (even indirectly) with -lthr.

A fix would probably either:
- prevent libthr from being dynamically unloaded once it has been loaded (probably the best option, but no idea how to achieve this)
- restore links to the libc stubs if libthr is unloaded (via a _fini() function that will be called by dlclose).



>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-threads mailing list