繁体   English   中英

使用 `clone()` 创建子进程。 为什么 `wait()` 不等待它终止?

[英]Created child process with `clone()`. Why does `wait()` not wait for it to terminate?

我正在尝试在单独的 UTS 名称空间内运行一些代码,并且我一直在尝试在 C 中执行此操作。

我有一个父 function,代码如下:

void run (char **args, int arglen) {
    printf("[*] Starting PID: %d\n", getpid());

    int i=1;
    cmd = concat_args(args, arglen);

    pid_t child_pid = clone(child_container, child_stack+STACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID, NULL);

    int status;
    wait(&status);
    printf("[*] Exit code: %d", status);
    return;
}

它创建了一个新进程并且应该等待它完成它的执行。

孩子有以下代码:

void child_container () {
    printf("This is the container!\n");
    printf("[*] Child PID: %d\n", getpid());
    system(cmd);
    printf("test\n");
}

我想在父母闭嘴之前运行任何命令。
问题是一些命令(例如/bin/ls )设法执行,其他(较慢的)命令(例如/bin/sh )在父级结束时关闭。

由于我使用了 wait function,我不明白为什么执行停止了。

我尝试在克隆之后在父级中使用睡眠,它延迟了程序的结束。 这应该意味着问题是父母没有等待它的孩子。

wait 和 waitpid 都试过了,进程还是结束了。

问题可能是新进程 ( /bin/sh ) 的产物吗? 我该如何解决?

编辑

这应该是一个可重现的例子

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

#define BUF_SIZE 0x3ff
#define STACK_SIZE 8192

static char child_stack[STACK_SIZE];
char *cmd;

char *concat_args(char **args, int arglen);
void child_container ();
void parse_command(char *cmd, char **args, int argc);
void run (char **args, int arglen);

char *concat_args(char **args, int arglen) {
    char *cmd = (char *)malloc((BUF_SIZE+1)*sizeof(char));
    memset(cmd, 0, BUF_SIZE+1);
    strncat(cmd, args[0], BUF_SIZE);
    for (int i=1; i<arglen; i++) {
        strncat(cmd, " ", BUF_SIZE);
        strncat(cmd, args[i], BUF_SIZE);
    }
    return cmd;
}

void run (char **args, int arglen) {
    printf("[*] Starting PID: %d\n", getpid());

    int i=1;
    cmd = concat_args(args, arglen);

    pid_t child_pid = clone(child_container, child_stack+STACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID, NULL);
    sleep(1);
    int status, e_code;
    e_code = wait(&status);
    if (e_code == -1) {
        perror("wait");
    }
    printf("[*] Exit code: %d\n[*] Status: %d\n", e_code, status);
    return;
}

void child_container () {
    printf("This is the container!\n");
    printf("[*] Child PID: %d\n", getpid());
    system(cmd);
    printf("test\n");
}

void parse_command(char *cmd, char **args, int argc) {
    if (!strcmp(cmd, "run")) {
        run(args, argc-2);
    } else {
        error("No such command!");
    }
}

int main(int argc, char **argv) {

    const char *format = "./container run [cmd] [args]";
    if (argc < 3) {
        error("Wrong format!\nThe commands must be formatted in the following way:\t./container run [cmd] [args]");
        return 0;
    }

    char *cmd = argv[1];
    char **args = &argv[2];

    parse_command(cmd, args, argc);
    return 0;
}

从克隆的手册页中提取

孩子终止信号
当子进程终止时,可以向父进程发送信号。 终止信号在标志的低字节 ( clone ()) 或 cl_args.exit_signal ( clone3 ()) 中指定。 如果此信号指定为SIGCHLD以外的任何信号,则父进程在使用wait (2) 等待子进程时必须指定 __WALL 或 __WCLONE 选项。 如果没有指定信号(即零),则当子进程终止时,父进程不会收到信号。

所以,答案很明确。 您没有指定信号,因此当您的孩子终止时您不会收到通知,因此 wait 无需等待。

    pid_t child_pid = clone(child_container, child_stack+STACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID | SIGCHLD, NULL);

应该解决问题(至少,没有它,你没有机会等待工作)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM