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

Bug#792029: libc6-amd64: Thread management in a cloned process error



Package: libc6-amd64
Severity: normal

Dear Maintainer,

It seems that I've found a bug in pthread part or libc.
The point is that software we develop requires to create and destroy threads inside a cloned process asynchronously (PTHREAD_CANCEL_ASYNCHRONOUS is set).
Everything is fine if CLONE_VM is not set, but we need it because main and child process _must_ share the same address space.
Below is an example that demonstrate the question.
Being compiled with CLONE_VM flag the program hangs at pthread_join while without CLONE_VM everything is fine.

We have tested the following example with musl library and everything worked as expected, but we cannot use it for the whole project.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

/* Compile with # gcc -o pthread_test -lpthread pthread_test.c */

#define CLONE 1

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_test(void *unused)
{
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_mutex_unlock(&mutex);
    pause();
    return NULL;
}

int test(void *unused)
{
    void *status;
    int r;
    pthread_t thread;
    pthread_mutex_lock(&mutex);
    if ((r = pthread_create(&thread, NULL, thread_test, NULL)) != 0) {
        printf("pthread_create returned %d\n", r);
        exit(1);
    }
    pthread_mutex_lock(&mutex);
    printf("cancelling thread\n");
    r = pthread_cancel(thread);
    printf("pthread cancel returned : %s(%d)\n", strerror(r), r);
    printf("joining thread\n");
    r = pthread_join(thread, &status);
    printf("pthread_join returned : %s\n", strerror(r));
    if (status == PTHREAD_CANCELED)
        printf("child was canceled\n");
    else
        printf("child exit status is %u\n", (unsigned)status);

    return 0;
}

int main(void)
{
#if CLONE
    void *stack = (void *)malloc(16384);
    if (clone(test, stack + 16383, CLONE_VM | CLONE_FS | CLONE_FILES, NULL) < 0) {
        printf("clone failed\n");
        exit(1);
    }
    waitpid(0, NULL, __WCLONE);
    return 0;
#else
    void *stack = (void *)malloc(16384);
    if (clone(test, stack + 16383, /*CLONE_VM |*/ CLONE_FS | CLONE_FILES, NULL) < 0) {
        printf("clone failed\n");
        exit(1);
    }
    waitpid(0, NULL, __WCLONE);
    return 0;
#endif
}


-- System Information:
Debian Release: stretch/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.0.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=ru_RU.UTF-8, LC_CTYPE=ru_RU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Reply to: