Well this works as I would expect.
But then again, it sets all the flags to 0.
Code:
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#define THREAD_MEMORY_SIZE (1024*1024)
int
child_func(void * data) {
static const char msg[] = "Child process is called\n";
pid_t pid = getpid();
pid_t ppid = getppid();
char buff[100];
sprintf(buff,"Child: pid=%d, ppid=%d\n",pid,ppid);
write(0, msg, sizeof(msg) - 1);
write(0, buff, strlen(buff));
return 1;
}
int
main() {
int pid;
void * memory;
static const char ERROR_MEMORY_ALLOC_FAILED[] = "ERROR-> Memory allocation failed\n";
static const char ERROR_CLONE_FAILED[] = "ERROR-> Unable to create a new child process\n";
if((memory = malloc(THREAD_MEMORY_SIZE)) == NULL) {
write(0, ERROR_MEMORY_ALLOC_FAILED, sizeof(ERROR_MEMORY_ALLOC_FAILED) - 1);
exit(1);
}
int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
CLONE_PARENT | CLONE_THREAD | CLONE_IO;
flags = 0;
flags |= SIGCHLD;
if((pid = clone(child_func, (memory + THREAD_MEMORY_SIZE), flags, NULL)) < 0) {
free(memory);
write(0, ERROR_CLONE_FAILED, sizeof(ERROR_CLONE_FAILED) - 1);
exit(1);
}
int status;
int r = waitpid(pid, &status, 0);
printf("Parent: pid=%d, ppid=%d\n",getpid(),getppid());
printf("waitpid returned %d, child status=%d\n",r,status);
free(memory);
exit(0);
}
$ ./a.out
Child process is called
Child: pid=5239, ppid=5238
Parent: pid=5238, ppid=4696
waitpid returned 5239, child status=256
$ ./a.out
Child process is called
Child: pid=5241, ppid=5240
Parent: pid=5240, ppid=4696
waitpid returned 5241, child status=256
But if I use the flags you specified, then it all goes to pot.
After several attempts, I saw this.
Code:
$ ./a.out
Child process is called
Parent: pid=5333, ppid=4696
Child: pid=5333, ppid=4696
waitpid returned -1, child status=0
pid and ppid are the same with your set of flags.
You can't successfully wait() for yourself.
And it's just a race condition between them to see which exits first - which is why you only ever see part of the total expected output.
So, what are you trying to achieve that pthread cannot?
This is what a clone() call looks like when called from pthread_create.
Code:
clone(child_stack=0x7fcf18630ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
parent_tidptr=0x7fcf186319d0, tls=0x7fcf18631700, child_tidptr=0x7fcf186319d0) = 5023
strace is your friend.