segfault with clone() and printf

2019-07-15 05:47发布

问题:

I'm trying to experiment with how clone() is implemented for threads in Linux 3.10.0-327.3.1.el7.x86_64

I'm running this piece of code and having occasional segfaults. I know if I use CLONE_THREAD then there's no way to check if the thread finished, but why does printf cause problems? How does the Pthread library handle this issue? Without the printfs there's no segfault.

#define STACK_SIZE (1ULL<<22) //4MB

int tmp = 10;

int threadfunc(void *ptr)
{
    printf("i'm here\n");
    tmp++;
    return 0;
}

int main()
{
    char *child_stack = malloc(STACK_SIZE);
    int child_pid = clone(&threadfunc, child_stack+(STACK_SIZE)-1, CLONE_THREAD|CLONE_SIGHAND|CLONE_VM|CLONE_FS|CLONE_FILES|SIGCHLD, NULL);

    printf("my pid: %d\n", getpid());
    printf("child pid: %d\n", child_pid);
    printf("tmp is: %d\n", val);

    return 0;
}

回答1:

The printf function doesn't understand that it's being called in a clone task; it is designed around the glibc pthread library.

What you're doing is similar to interrupting a printf with an asynchronous signal, and re-entering printf from the signal.

How the library handles the issue is that it uses clone as part of a more complicated implementation of threads, which "dresses up" the cloned task with a thread identity. This thread identity allows printf to lock a mutex around the stream operation.

What is the thread identity? What it means is that a thread-related function in the C library can inquire, in some way, "what thread is calling me?" to obtain an ID, which maps to a thread descriptor structure. The clone function alone won't set up this identity.