[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#233589: waitpid fails to wait for termination of a process started from a different thread



Package:glibc
Version:2.3.2-90

Waitpid fails with errno 10 when called from a thread other than the one
that started the process being waited on. This happens regardless of whether
the threads were created with pthread_create() or clone() (see sample code).

The man pages installed on my system (see uname -a below), indicate that
libpthread/glibc support this behavior. From the LINUX NOTES section of the
man page for waitpid(2):

... since Linux 2.4  a thread can, and by default will, wait on children of
other threads in the same thread group...

my system
>uname -a
Linux amd64 2.4.21-193-smp #1 SMP Thu Jan 22 16:52:24 UTC 2004 x86_64 x86_64
x86_64 GNU/Linux

The sample code below demonstrates this problem.

<snippet>

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <pthread.h>

static pthread_t processThreadId= 0;
extern char **environ;
#define STACKSIZE (1024 * 64)

#define USE_CLONE_FOR_THREADS 1
#define CLONE_FLAGS CLONE_PARENT | CLONE_THREAD | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND | CLONE_VM

#if USE_CLONE_FOR_THREADS
int my_pthread_create( pthread_t *pthread, pthread_attr_t * attr, void
*(start_routine)(void *), void *arg)
{
   void *stack = (void *)(long)malloc ((size_t)STACKSIZE);
   fprintf(stderr, "my_pthread_create::Using clone\n" );
   *pthread = (pthread_t)clone( (int(*)(void *))start_routine, (char *)stack
+ STACKSIZE, CLONE_FLAGS, arg );
   return (*pthread>0?0:-1);
}
#else
#define my_pthread_create pthread_create
#endif

int my_system (const char *command)
{
    int pid, status;
    void *stack = malloc( 1024 * 64 );

    if (command == 0)
        return 1;
    fprintf(stderr,"my_system::Using fork\n");
    pid = fork();

    if (pid == -1)
        return -1;

    if (pid == 0) {
        char *argv[4];
        argv[0] = "sh";
        argv[1] = "-c";
        argv[2] = (char *)command;
        argv[3] = 0;
        fprintf(stderr,"my_system::Chaining\n");
        execve("/bin/sh", argv, environ);
        fprintf(stderr,"my_system::Chaining failed!\n");
        exit(127);
    }
    return pid;
}

void *WaitThread(void *arg)
{
    int pid     = *(int *)arg;
    int rpid    = 0;
    int status  = 0;

    fprintf(stderr, "WaitThread::Start\n");
    while(1)
    {
        fprintf(stderr,"WaitThread::Waiting on pid: %d\n",pid);
        rpid = waitpid(pid, &status, __WCLONE );
        if (rpid == -1)
        {
            fprintf(stderr,"WaitThread::Wait failed errno: %d\n",errno);
            if (errno != EINTR)
                break;
        }
        else
        {
            printf("WaitThread::success child status: %d\n",status);
            break;
        }
    }
    fprintf(stderr, "WaitThread::End\n");
    return (void *)(long)rpid;
}

void *ProcessThread(void *arg)
{
    int pid = 0;
    pthread_t waitThreadId;

    fprintf(stderr,"ProcessThread::Start\n");
    pid = my_system("/bin/sleep 100");

    if (pid == -1 )
    {
        fprintf(stderr, "ProcessThread::my_system failed errno : %d\n",
errno);
        exit(pid);
    }
    else
    {
        fprintf(stderr, "ProcessThread::Child pid = %d\n", pid);
    }
    my_pthread_create(&waitThreadId, 0, WaitThread, (void *)&pid);
    fprintf(stderr,"ProcessThread::End\n");
    return 0;
}

int main()
{
    fprintf(stderr,"Main::Start\n");

    my_pthread_create(&processThreadId, 0, ProcessThread, 0);

    sleep(1);
    fprintf(stdout,"<Press return to end>");
    fflush(stdout);
    getchar();

    fprintf(stderr,"Main::End\n");
    return 0;
}

</snippet>

Here is the output of this program when using the clone() system call to
create threads, the behavior is the same when using pthread_create():

Main::Start
my_pthread_create::Using clone
ProcessThread::Start
my_system::Using fork
my_system::Chaining
ProcessThread::Child pid = 8678
my_pthread_create::Using clone
WaitThread::Start
WaitThread::Waiting on pid: 8678
WaitThread::Wait failed errno: 10
WaitThread::End
ProcessThread::End
<Press return to end>
Main::End

Thanks in advance for any feedback on this.

Cris.




Reply to: