Search code examples
c++linuxc++11lambdastd-function

How can i pass pointer of function from std::function to Linux clone?


I have a class that looks like this:

class MyThread{
private:
    pid_t pid;
    size_t stack_size;
    char* child_stack;
    void* child_stack_end; 

public:

// --methods--

    MyThread(std::function<int(void*)> const& fun) {
        stack_size = 1024*10;
        child_stack = new char[stack_size];
        child_stack_end = child_stack + stack_size;

        int (*const* ptr)(void*) = fun.target<int(*)(void*)>();

        pid = clone(*ptr, child_stack_end, CLONE_VM | 
        CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD, 0);
    }
}

And I want to test it with my merge sort function with lambda (not to create constructor of MyThread class witch takes args of merge_sort_thread function + clone() need int(*)(void*) function as 1 argument):

MyThread([first, center](void* arg){
    return merge_sort_thread(first, center);
});

Then I trying this code it returns SIGSEGV. I checked with GDB, variable ptr is equal 0x0. How I can fix this?

Merge sort function looks like:

template<typename T>
static int merge_sort_thread(T first, T last){ // working with pointers 
   //sorting
}

Well the main idea is to use MyThread class like std::thread with lambda

std::thread([first, center](){
    return merge_sort_thread(first, center);
});

Solution

  • Simply put, you can’t. A capturing lambda is not compatible with a function pointer, and your call to fun.target<int(*)(void*)> consequently returns a null pointer. Passing that to clone causes the segfault.

    That’s why clone has a void* args argument to pass a (pointer to) arbitrary data into the callback function: this effectively fulfils the role of the capture. If you want to pass a custom std::function into clone you will need to wrap it into a function with signature int(void*), which internally unwraps that std::function from its void* argument and calls it.