Atri Robot
Atri Robot

Reputation: 93

Correctly allocate stack for clone a thread

So I want to create a thread without CLONE_FILES flag. I try to call clone directly, but has some strange problem. I think it is related to incorrect memory allocation.

#ifndef _GNU_SOURCE
    #define _GNU_SOURCE
#endif
#include <iostream>
#include <sys/mman.h>
#include <pthread.h>
#include <unistd.h>

const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_SYSVSEM
            | CLONE_SIGHAND | CLONE_THREAD
            | CLONE_SETTLS | CLONE_PARENT_SETTID
            | CLONE_CHILD_CLEARTID
            | 0);

static int cloneThread(void* arg)
{
    long arg2 = (long)arg + (long)arg;
    long* arg2_ptr = &arg2;
    return 0;
}

int main(int argc, char** argv)
{
    const int STACK_SIZE = 0x800000;
    void* stackaddr = malloc(STACK_SIZE);
    void* stacktop  = (char*)stackaddr + STACK_SIZE; // assuming stack going downwards

    clone(cloneThread, stacktop, clone_flags, (void*)1);
    sleep(1); // wait for cloneThread running before exit
}

As you can see here, I am using malloc for stack allocation. lldb shows the program crashes at the beginning of cloneThread. But if I remove long* arg2_ptr = &arg2;, the program exit successfully.

I also read source code of pthread_create.c, allocatestack.c. With strace, I replaced malloc with the following

void* stackaddr = mmap(NULL, STACK_SIZE, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0);
mprotect(stackaddr, STACK_SIZE, PROT_READ|PROT_WRITE);

But it has the same behavior as using malloc. So how should I use clone?

OS: Ubuntu 18.04 LTS, g++ 7.3.0

Upvotes: 1

Views: 674

Answers (1)

caf
caf

Reputation: 239011

When you supply the CLONE_SETTLS, CLONE_PARENT_SETTID and CLONE_CHILD_CLEARTID flags you must provide the newtls, ptid and ctid arguments to clone() respectively.

If all you want is a normal thread with a separate FD table though, just use pthread_create() and call unshare(CLONE_FILES) as the first operation in the new thread.

Upvotes: 2

Related Questions