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