Ishan Khare
Ishan Khare

Reputation: 1767

C clone function not executing with CLONE_NEWPID | SIGCHLD flags

I have the following code:

#define _GNU_SOURCE
#include<sched.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>

static char child_stack[2048];

int x = 10;

static int child_fn() {
    printf("Pid: %ld\n", (long) getpid());
    return 0;
}

int main() {
    printf("before= %d\n", x);
    errno = 0;
    pid_t child_pid = clone(&child_fn, (void *) child_stack+1024, CLONE_NEWPID | SIGCHLD, NULL);
    if(child_pid == -1) {
        printf("%s\n", strerror(errno));
        return 0;
    } else {
        printf("clone()= %ld\n", (long) child_pid);
        printf("after= %d\n", x);

        while(waitpid(-1, NULL, 0) < 0 && errno == EINTR) {
            printf("waiting\n");
            continue;
        }

        return 0;
    }
}

the output I get is:

before= 10
clone()= 16
after= 10

This means that the child_fn did get assigned a Pid, which is child_pid. But the printf inside the child_fn either didn't get executed, or it may be printing in a different stdout scope? Either way, what can be the reason for this, and how to debug it. I'm just starting with namespaces so don't know much about them.

Upvotes: 0

Views: 504

Answers (1)

larsks
larsks

Reputation: 312370

If I run your original code using gdb, I see that it is failing with a SIGSEGV:

$ gcc -o clone clone.c
$ sudo gdb ./clone
(gdb) set follow-fork-mode child
(gdb) run
Starting program: /home/lars/tmp/clone 
before= 10
[New process 10768]
clone()= 10768
after= 10

Thread 2.1 "clone" received signal SIGSEGV, Segmentation fault.
[Switching to process 10768]
0x00007ffff7a5e9de in vfprintf () from /lib64/libc.so.6

I suspect that your child_stack is too small. You've allocated 2048 bytes, but you're only using half of that. If I modify the clone call to look like this:

pid_t child_pid = clone(&child_fn, (void *) child_stack+2048, CLONE_NEWPID | SIGCHLD, NULL);

Then on my system it seems to run correctly:

$ sudo gdb ./clone
(gdb) set follow-fork-mode child
(gdb) run
Starting program: /home/lars/tmp/clone 
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.24-9.fc25.x86_64
before= 10
[New process 10807]
clone()= 10807
after= 10
Pid: 1
[Inferior 2 (process 10807) exited normally]

Upvotes: 1

Related Questions