The SIGCHLD signal is sent to the parent of a child process when it exits, is interrupted, or resumes after being interrupted. By default the signal is simply ignored.

在子进程execvp的程序为:

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <signal.h>
	
int main() {
    char * argv[] = {"ls", "-a", "/home", 0};
    printf("[child]before exe\n");
    execvp(argv[0], argv);
    return -1;

} 其中还有一个execvp的调用,这同样会导致子进程suspend,因为子进程被ptrace 跟踪了。

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <signal.h>

static int a = 0;

int child() {
    a = 1;
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);

    char * argv[] = {"./exec", 0};
    printf("before exe\n");
    a = 2;
    printf("[3] a: %d\n", a);
    execvp(argv[0], argv);

    return -1;
}

static void cld_handler(int n) {
    printf("cld_handler\n");
}

int main() {
    int ret;
    int status;
    int pid = fork();

    if(pid == 0) {
        //child
        exit(child());
    }

    ret = waitpid(pid, &status, WUNTRACED); // 等待子进程最外面的execvp
    //for(;;);
    ptrace(PTRACE_CONT, pid, NULL, NULL); //如果PTRACE_CONT换成PTRACE_DETACH,
    //则第二execvp不会导致子进程挂起

    ret = waitpid(pid, &status, WUNTRACED); // 等待子进程最里面的execvp
    for(;;); // 因为这个死循环的存在,子进程仍然suspend在那

    signal(SIGCHLD, cld_handler);
    //a = 3;
    printf("[2] a: %d\n", a);

    return 0;
}