pthread and daemon() problem

Ricard Wanderlof ricard.wanderlof at axis.com
Tue Jan 5 13:45:15 UTC 2010


We've been experiencing a problem with applications which first use 
daemon() and then threading using pthreads (linuxthreads.old). (One 
example is stunnel, but there are others).

The problem is that when the first thread is created, the initial thread 
goes to sleep and doesn't wake up.

This has been addressed earlier, see for instance 
http://lists.uclibc.org/pipermail/uclibc/2007-June/038904.html .

In trying to come to grips with this problem, I noticed that one of our 
platforms, which uses gcc 3.4.4, worked fine, whereas on another platform 
where we use gcc 4.2.4, there were problems. In both cases the CPU core is 
an ARM 926 EJ-S (although the actual systems are different which [ long 
explanation omitted ] is why we use different compiler versions for the 
two platforms).

Using ltrace to capture system and library calls from stunnel, I finally 
arrived at the following:

In libpthread/linuxthreads.old/pthread.c, pthread_initialize() sets the 
PID of the initial thread by using getpid(). (The PID is stored in 
__pthread_initial_thread.p_pid).

Now, for gcc 4.2.4, this function is called prior to main(), because it is 
marked as __attibute__((constructor)) in its prototype. Thus, the initial 
thread PID is set to the PID of the application.

For gcc 3.4.4, the function is not called in this way [because it 
recognizes but does not do anything with the constructor attribute???]. 
Instead, pthread_initialize_manager() detects that pthread_initialize() 
hasn't been called, and calls it. Thus, in this case, the initial thread 
PID is set to the PID of the process where the first call to 
pthread_create() is made.

The later behavior seems more correct to me, but I'm getting out of my 
depth here, and can't really envision all the implications ...

I don't know why gcc 4.2.4 and 3.4.4 work differently, but I haven't 
looked in any documentation (yet) either. Any pointer here would be 
helpful. (The two gcc versions where built using buildroot, incidentally, 
without any added patches).

One solution which appears to work is to remove the 
__attribute__((constructor)) from the pthread_innitialize() prototype in 
pthread.c . Since it works fine without being called as a constructor for 
gcc-3.4.4, it should work fine in gcc-4.2.4 too. I tried this, and at 
least stunnel then behaves as expected.

However, there is a note about the fact that pthread_initialize() 
_should_ be called as early as possible, "since the program could capture 
the signal mask with e.g. sigsetjmp before creating the first thread" 
(snipped from comment in the file). I don't know whether this is an issue 
in practice.

Another solution would be to move the initialization of 
__pthread_initial_thread.p_pid from pthread_initialize() to 
pthread_initialize_manager(). I haven't tried this so I don't know if 
there are any ill effects. A more foolproof solution would be to 
initialize it in both places. Since the first call to libpthread that the 
program sees would likely be pthread_create(), it would seem safe both 
ways.

Yes, I could provide a patch, but I thought I'd bring this up for 
discussion before barking up the completely wrong tree.

regards,

/Ricard
-- 
Ricard Wolf Wanderlöf                           ricardw(at)axis.com
Axis Communications AB, Lund, Sweden            www.axis.com
Phone +46 46 272 2016                           Fax +46 46 13 61 30


More information about the uClibc mailing list