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: