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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.