M
mike
I've got an issue with an application I've developed that uses a
combination of threads (pthreads) and fork()'d processes.
In short, my parent process has a handful of threads that run to
perform various tasks; when a new request comes into the parent
process, it forks off a new child to handle the request; one of the
first things the child does is initiate a library that has a date
class that calls tzset().
My parent process also logs the requests from a thread, which writes
the date to the log using localtime_r(), which also calls tzset().
The problem, is that one of out every x child processes fork()'d
simply hangs at a lock in tzset() when the library is initialized.
I've reproduced this by creating a very simple test program, that
simply calls tzset() over and over from a thread, while it forks, and
then calls tzset() in the child process- I can get it to hang almost
immediately.
and this only seems to happen on my Linux machines (CentO/S 5.5)- my
FreeBSD (8.0) runs my test program file, without any locks.
So my question is: if I fork() while tzset() is holding a lock in the
parent process, will the lock get copied to the child process locked?
Is this a known result? is there a way around this?
Test program, which is just a super simple version of what I see in my
real app, and gdb output below, which is when I attached to a child
process that had hung.
Mike
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
static void* setter(void*)
{
while(1)
{
tzset();
}
return NULL;
}
int main(void)
{
pthread_t thread;
pthread_create(&thread, NULL, &setter, NULL);
signal(SIGCHLD, SIG_IGN);
while(1)
{
switch(fork())
{
case 0:
{
fprintf(stderr, "CHILD >> tzset()\n");
tzset();
exit(1);
}
break;
case -1:
{
fprintf(stderr, ">> failed to fork()
\n");
}
break;
default:
{
;
}
}
usleep(1000);
}
return 0;
}
Reading symbols from /home/mike/thr/test...done.
Attaching to program: /home/mike/thr/test, process 8397
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols
found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols
found)...done.
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols
found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging
symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x0000003512cdfade in __lll_lock_wait_private () from /lib64/libc.so.6
(gdb) bt
#0 0x0000003512cdfade in __lll_lock_wait_private () from /lib64/
libc.so.6
#1 0x0000003512c8d20b in _L_lock_1920 () from /lib64/libc.so.6
#2 0x0000003512c8d0f1 in tzset () from /lib64/libc.so.6
#3 0x0000000000400811 in main () at test.cpp:32
(gdb) info threads
* 1 Thread 0x2ab3c2e9dbb0 (LWP 8397) 0x0000003512cdfade in
__lll_lock_wait_private () from /lib64/libc.so.6
combination of threads (pthreads) and fork()'d processes.
In short, my parent process has a handful of threads that run to
perform various tasks; when a new request comes into the parent
process, it forks off a new child to handle the request; one of the
first things the child does is initiate a library that has a date
class that calls tzset().
My parent process also logs the requests from a thread, which writes
the date to the log using localtime_r(), which also calls tzset().
The problem, is that one of out every x child processes fork()'d
simply hangs at a lock in tzset() when the library is initialized.
I've reproduced this by creating a very simple test program, that
simply calls tzset() over and over from a thread, while it forks, and
then calls tzset() in the child process- I can get it to hang almost
immediately.
and this only seems to happen on my Linux machines (CentO/S 5.5)- my
FreeBSD (8.0) runs my test program file, without any locks.
So my question is: if I fork() while tzset() is holding a lock in the
parent process, will the lock get copied to the child process locked?
Is this a known result? is there a way around this?
Test program, which is just a super simple version of what I see in my
real app, and gdb output below, which is when I attached to a child
process that had hung.
Mike
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
static void* setter(void*)
{
while(1)
{
tzset();
}
return NULL;
}
int main(void)
{
pthread_t thread;
pthread_create(&thread, NULL, &setter, NULL);
signal(SIGCHLD, SIG_IGN);
while(1)
{
switch(fork())
{
case 0:
{
fprintf(stderr, "CHILD >> tzset()\n");
tzset();
exit(1);
}
break;
case -1:
{
fprintf(stderr, ">> failed to fork()
\n");
}
break;
default:
{
;
}
}
usleep(1000);
}
return 0;
}
Reading symbols from /home/mike/thr/test...done.
Attaching to program: /home/mike/thr/test, process 8397
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols
found)...done.
[Thread debugging using libthread_db enabled]
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /usr/lib64/libstdc++.so.6...(no debugging symbols
found)...done.
Loaded symbols for /usr/lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols
found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols
found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging
symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x0000003512cdfade in __lll_lock_wait_private () from /lib64/libc.so.6
(gdb) bt
#0 0x0000003512cdfade in __lll_lock_wait_private () from /lib64/
libc.so.6
#1 0x0000003512c8d20b in _L_lock_1920 () from /lib64/libc.so.6
#2 0x0000003512c8d0f1 in tzset () from /lib64/libc.so.6
#3 0x0000000000400811 in main () at test.cpp:32
(gdb) info threads
* 1 Thread 0x2ab3c2e9dbb0 (LWP 8397) 0x0000003512cdfade in
__lll_lock_wait_private () from /lib64/libc.so.6