Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a real thread with clone() on Linux?

I am trying to create a new thread using clone(). With the following code (...):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define _SCHED_H 1
#define __USE_GNU 1
#include <bits/sched.h>

#define STACK_SIZE 4096

int func(void *arg) {
    printf("Inside func.\n");
    sleep(1);
    printf("Terminating func...\n");

    return 0;
}

int main() {
    printf("This process pid: %u\n", getpid());
    char status_file[] = "/proc/self/status";
    void *child_stack = malloc(STACK_SIZE);
    int thread_pid;

    printf("Creating new thread...\n");
    thread_pid = clone(&func, child_stack+STACK_SIZE, CLONE_SIGHAND|CLONE_FS|CLONE_VM|CLONE_FILES, NULL);
    printf("Done! Thread pid: %d\n", thread_pid);

    FILE *fp = fopen(status_file, "rb");

    printf("Looking into %s...\n", status_file);

    while(1) {
        char ch = fgetc(fp);
        if(feof(fp)) break;
        printf("%c", ch);
    }

    fclose(fp);

    getchar();

    return 0;
}

I get the following:

This process pid: 10839
Creating new thread...
Done! Thread pid: 10840
Inside func.
Looking into /proc/self/status...
Name:   threadTest02
State:  R (running)
Tgid:   10839
Pid:    10839
PPid:   4777
TracerPid:      0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 4 20 24 27 30 46 107 123 124 1000 
VmPeak:     4300 kB
VmSize:     4300 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:       356 kB
VmRSS:       356 kB
VmData:      188 kB
VmStk:       136 kB
VmExe:         4 kB
VmLib:      1884 kB
VmPTE:        32 kB
VmSwap:        0 kB
Threads:        1
SigQ:   0/22869
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed:   3
Cpus_allowed_list:      0-1
Mems_allowed:   00000000,00000001
Mems_allowed_list:      0
voluntary_ctxt_switches:        1
nonvoluntary_ctxt_switches:     1
Terminating func...

So, in short, what does my program do? It creates a new thread with clone and prints its /proc/self/status, so that I can see its status. Since my thread sleeps for 1 second, it is still alive when /proc/self/status is printed.

However, there are at least two things that make my thread not behave like a common thread. First, as you could see above, the process' pid is 10839 and my thread's pid is 10840. So, the process and my thread don't have the same pid, as occurs in a common thread. Second, even after my thread was created, the Threads: field of my process' /proc/self/status file is still 1. So, my thread seems not to be recognized as a thread.

My question is, what is missing in my code? What do I have to do to make my thread behave like a common thread? Is there any option missing in the third argument of clone?

like image 574
LuisABOL Avatar asked Apr 07 '13 02:04

LuisABOL


1 Answers

You may want to see the flag CLONE_THREAD, it will place the new thread in the same thread group as the calling process.

Once you give the CLONE_THREAD, it will make the new thread have the same pid and ppid as the calling process. It is used in posix threads. Below is an output from my system. the LWP column says that is is now a light weight process and has different TID

UID        PID  PPID   LWP  C NLWP    SZ   RSS PSR STIME TTY          TIME CMD
anukalp  18398  9638 18398  0    2   464   456   0 10:56 pts/3    00:00:00 ./a.out
anukalp  18398  9638 18399  0    2   464   456   1 10:56 pts/3    00:00:00 ./a.out

Also the output of /proc/self/status changes, I have added a couple of printfs:

[anukalp@localhost ~]$ ./a.out

This process pid: 18398
Creating new thread...
Done! Thread pid: 18399 /* This is now thread id, available to caller of clone */
getpid(): ad pid: 18399
Inside func.
getpid(): 18398
getppid(): 9638
Looking into /proc/self/status...
Name:   a.out
State:  R (running)
Tgid:   18398
Pid:    18398
PPid:   9638
TracerPid:      0
Uid:    500     500     500     500
Gid:    500     500     500     500
FDSize: 256
Groups: 7 19 22 80 81 82 83 100 490 500 
VmPeak:     1856 kB
VmSize:     1856 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:       248 kB
VmRSS:       248 kB
VmData:      168 kB
VmStk:       140 kB
VmExe:         4 kB
VmLib:      1516 kB
VmPTE:        16 kB
VmSwap:        0 kB
Threads:        2
SigQ:   1/14050
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed:   00000000,000000ff
Cpus_allowed_list:      0-7
voluntary_ctxt_switches:        1
nonvoluntary_ctxt_switches:     0
Inside thread: thread pid = 18398
Inside thread: thread ppid = 9638

Please let me know if this helps!

like image 195
anukalp Avatar answered Nov 02 '22 23:11

anukalp