SEGFAULT in pthread_getspecific() in _init()

"Dr. Uwe Girlich" <[email protected]>
Newsgroups gmane.linux.ngpt.devel
Message-ID <[email protected]>
Hello list!

Are there any restrictions on usable pthread_* function in other shared library
_init() hooks?

I found, that pthread_key_create() & pthread_getspecific() called in a _init
function of a shared library will result in a SEGFAULT in pth_key_getdata(),
because at this time, pth_get_current() gave me a NULL pointer as current.

There are several possible solutions:
1) Never allow pthread_getspecific() in _init().
2) Link the shared library against libpthread.so, so _init() of NGPT will be
        called before my own _init() function.
3) Apply the attached patch to check for a NULL pointer in pth_key_getdata().

Solutions 1) and 2) are impossible in my current project, so I had to correct
the symptoms and not the real cause.

Attached are 2 source files for main and the shared library. Compiled with 
-DWITH_SELFINIT, _init() in the shared library will be activated and crash,
with -UWITH_SELFINIT the main program calls the init function itself and all is
OK. Make sure not to link the shared library itself against -lpthread.
-lpthread should stay at the link line for the executable only (would be
solution 2).

Bye, Uwe

-- 
Dr. Uwe Girlich              email: [email protected]
Philosys Software GmbH       www: www.philosys.de
Edisonstrasse 6              phone: +49 89 321407-44
D-85716 Unterschleissheim    fax: +49 89 321407-12
library-keygetdata.diff (text/plain, 468 B)
diff -u -r --exclude='*.o' ngpt-2.0.1-orig/pth_data.c ngpt-2.0.1-production/pth_data.c
--- ngpt-2.0.1-orig/pth_data.c	Fri Aug  9 21:31:32 2002
+++ ngpt-2.0.1-production/pth_data.c	Tue Sep 10 13:24:12 2002
@@ -105,7 +105,7 @@
         return NULL;
     if (!pth_keytab[key].used)
         return NULL;
-    if (current->data_value == NULL)
+    if (current == NULL || current->data_value == NULL)
         return NULL;
     return (void *)current->data_value[key];
 }
gs.c (text/plain, 264 B)
#include <stdio.h>

#ifndef WITH_SELFINIT
void shlib_init(void);
#endif

int
main(int argc, char** argv)
{
	char	*fname = "main";
	fprintf(stderr,"%s: START\n", fname);
#ifndef WITH_SELFINIT
	shlib_init();
#endif
	fprintf(stderr,"%s: END\n", fname);
	return 0;
}
shlib.c (text/plain, 698 B)
#include <pthread.h>
#include <stdio.h>

pthread_once_t	initialized = PTHREAD_ONCE_INIT;
pthread_key_t	key = 0;

void
shlib_init(void)
{
	char	*fname = "shlib_init";
	int	error;
	int	*data;
	fprintf(stderr,"%s: START\n", fname);

	fprintf(stderr,"%s: call pthread_key_create(&key)\n", fname);
	error=pthread_key_create(&key,NULL);
	fprintf(stderr,"%s: pthread_key_create()=%d key=%d\n", fname, error, key);
	fprintf(stderr,"%s: call pthread_getspecific()\n", fname);
	data = pthread_getspecific(key); /* we expect here NULL */
	fprintf(stderr,"%s: pthread_getspecific()=%p\n", fname, data);

	fprintf(stderr,"%s: END\n", fname);
}


#ifdef WITH_SELFINIT
void
_init(void)
{
	shlib_init();
}
#endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.