Re: dietlibc (0.31), fork and pthreads
Ingo Struck <[email protected]>
| Newsgroups | gmane.linux.lib.dietlibc |
|---|---|
| Message-ID | <[email protected]> |
Hello again,
it seems that I can explain now why your fd 0 is closed
(compiled a debug version of diet-0.32). I am sorry to say that I do not
know a good fix for it, because obviously the libpthread code relies on
an internal pipe for the "manager" thread.
Explanation:
If you do not have any call to a pthread function before
you pipe() / fork() the pthread library code is not initialized;
there is no call to __thread_init, hence no call to __manager_thread_init,
so the call to __thread_manager_close works on an uninitialized __manager_pipe
(both entries are 0).
So
close(mgr_recv_fd);
close(mgr_send_fd);
in libpthread/pthread_internal.c, line 422 and 423 read
close(0);
close(0);
This is why the call to fork() closes fd 0 within the child branch of fork.
If, OTOH you add a call to e.g. pthread_create before you pipe/fork, the
pthread code creates a pipe and you will get the following result:
before: (5,6), child: (3,4), parent: (5,6), (see my attached forktest.c).
Proposed workarounds:
a) add a global "initialized" flag in pthread and do not call
__thread_manager_close if unset
b) exit__thread_manager_close if 0 == check __manager_pipe[1]
This is the output of the attached forktest.c w/ a debug dietlib:
----
ingo@neo:~$ ./forktest_diet_pthreads
__thread_init: start...
__thread_init: start mgr...
__managed_start: 14544 pre suspend
pthread_handle_sigrestart(63) in 14544
__managed_start: 14544, parameter 0x401359
manager pre start sleep
__manager_thread_init: mgr restart...
pthread_handle_sigrestart(63) in 14543
__manager_thread_init: thread-mgr should now be started...
__manager_thread: do func 00401261 ce3e1d40
__managed_start: 14545 pre suspend
pthread_handle_sigrestart(63) in 14545
__managed_start: 14545, parameter 0x400110
(thread created) __MGR_thread_start_new: created thread 14545
pthread_handle_sigrestart(63) in 14543
forktest.c:25 [before fork] - pipe() returned 5,6
forktest.c:33 [child] - pipe() returned 3,4
__thread_doexit: 14546
forktest.c:40 [parent] - pipe() returned 5,6
__thread_doexit: 14543
pthread_handle_sigcancel(62): sigcancel 14544
pthread_handle_sigcancel: kill from main: 14543
pthread_handle_sigcancel(62): sigcancel 14545
pthread_handle_sigcancel: 14545 : cancel event
(thread exit) pthread_handle_sigcancel(62): sigcancel 14543
pthread_handle_sigcancel: 14543 : cancel event for MAIN
-----
ingo@neo:~$ cat forktest.c
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
void*thread(void*arg) {
if (0) { arg=0; }
printf("(thread created) ");
sleep(1);
printf("(thread exit) ");
return 0;
}
int main(int argc, char **argv) {
int fds[2];
/*= {0};*/
int res;
pthread_t t;
if ((pthread_create(&t,0,thread,0))!=0)
return -1;
pipe(fds);
printf("%s:%d [%s] - pipe() returned %d,%d\n", __FILE__,
__LINE__, "before fork", fds[0], fds[1]);
close(fds[0]);
close(fds[1]);
pid_t pid = fork();
if (pid == 0) {
pipe(fds);
printf("%s:%d [%s] - pipe() returned %d,%d\n", __FILE__,
__LINE__, "child", fds[0], fds[1]);
close(fds[0]);
close(fds[1]);
}
else {
pipe(fds);
printf("%s:%d [%s] - pipe() returned %d,%d\n", __FILE__,
__LINE__, "parent", fds[0], fds[1]);
close(fds[0]);
close(fds[1]);
waitpid(pid, &res, 0);
}
return 0;
}
Kind regards
Ingo Struck