Subject: pkg/7433: pthread_init() not called
To: None <gnats-bugs@gnats.netbsd.org>
From: Andreas Gustafsson <gson@araneus.fi>
List: netbsd-bugs
Date: 04/21/1999 06:35:54
>Number:         7433
>Category:       pkg
>Synopsis:       pthread_init() not called
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager (NetBSD software packages system manager)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 21 06:35:00 1999
>Last-Modified:
>Originator:     Andreas Gustafsson
>Organization:
Araneus Information Systems Oy
>Release:        1.3.2
>Environment:

System: NetBSD guava.araneus.fi 1.3.2 NetBSD 1.3.2 (GUAVA) #0: Wed Feb 17 10:21:50 EET 1999 gson@guava.araneus.fi:/z/src-1.3/sys/arch/i386/compile/GUAVA i386


>Description:

When linking a C program with the pthreads shared library from the
devel/mit-pthreads package, pthread_init() is not called automatically
on startup like it is supposed to.  The typical symptom of this is
that the first call to a library function using thread-specific data
leads to a core dump in pthread_getspecific().

This problem occurs on the i386, and presumably also on other
platforms using the a.out object format.  It does not occur
with static linking.

The call to pthread_init() is supposed to happen by means of the C++
static constructor mechanism, but this fails on a.out platforms unless
the shared library is explicitly linked with /usr/lib/c++rt0.o as the
first object on the ld command line.

>How-To-Repeat:

   $ cat test.c
   #include <stdio.h>
   #include <time.h>
   int main(int argc, char **argv)
   {
       time_t now;
       struct tm *tm;
       time(&now);
       tm = localtime(&now);
   }
   $ /usr/pkg/pthreads/bin/pgcc test.c
   $ a.out
   Segmentation fault (core dumped)
   $ /usr/pkg/pthreads/bin/pgcc -static test.c
   $ a.out
   $

>Fix:

Depends on the NetBSD version.  On NetBSD-current, add the following
patch to the /usr/pkgsrc/devel/mit-pthreads/patches directory:

--- config/Makefile.in.orig	Wed Apr 21 14:11:42 1999
+++ config/Makefile.in	Wed Apr 21 14:47:05 1999
@@ -41,6 +41,10 @@
 
 .include <bsd.lib.mk>
 
+.if (${OBJECT_FMT} == "a.out")
+SHLIB_LDSTARTFILE = /usr/lib/c++rt0.o
+.endif
+
 $(OBJS) : $(config) $(types) $(paths)
 
 Makefile: ${srcdir}/config/Makefile.in

On 1.3.2/1.3.3, a more elaborate patch is needed because <bsd.lib.mk>
does not expand SHLIB_LDSTARTFILE on the a.out ld command line.  The
following patch achieves the desired effect by duplicating some code
from bsd.lib.mk in the Makefile.  It has only been tested on 1.3.2.

--- config/Makefile.in.orig	Wed Apr 21 12:14:21 1999
+++ config/Makefile.in	Wed Apr 21 16:01:07 1999
@@ -39,6 +39,25 @@
 .include "${srcdir}/net/Makefile.inc"
 .include "${srcdir}/scripts/Makefile.inc"
 
+# On a.out platforms, override the shared library linking rule to 
+# link with c++rt0.o so that pthread_init() gets called.
+# On -current we could just set SHLIB_LDSTARTFILE=/usr/lib/c++rt0.o,
+# but the SHLIB_LDSTARTFILE macro is not expanded on the a.out linker
+# command line in 1.3.2 or 1.3.3.
+
+.if (${MACHINE_ARCH} != "alpha" && ${MACHINE_ARCH} != "mips")
+
+SHLIB_MAJOR != . ${.CURDIR}/shlib_version ; echo $$major
+SHLIB_MINOR != . ${.CURDIR}/shlib_version ; echo $$minor
+
+lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}: lib${LIB}_pic.a ${DPADD}
+	@echo building shared ${LIB} library \(version ${SHLIB_MAJOR}.${SHLIB_MINOR}\)
+	@rm -f lib${LIB}.so.${SHLIB_MAJOR}.${SHLIB_MINOR}
+	$(LD) -x -Bshareable -Bforcearchive \
+	    -o ${.TARGET} /usr/lib/c++rt0.o lib${LIB}_pic.a ${LDADD}
+
+.endif
+
 .include <bsd.lib.mk>
 
 $(OBJS) : $(config) $(types) $(paths)
>Audit-Trail:
>Unformatted: