【问题标题】:Can't kill PID started with spawn无法杀死从 spawn 开始的 PID
【发布时间】:2017-04-19 13:17:50
【问题描述】:

几天前,我问here 如何不使用fork() 使用C 启动程序。这个解决方案工作正常......除了我不能杀死这个子进程! 我的程序(在本例中为“rbfeeder”)有一些线程......当我发送终止信号时,只有线程被终止(我认为)。我做错了什么?

这是用于“启动”rbfeeder 的代码:

/*
 * Start dump1090, if not running
 */
void startDump(void) {

    if (p_dump != 0) {
        log_level(8, "Looks like dump is already running.\n");
        return;
    }

    pid_t ret = run_cmd("/home/jmaurin/dev/client/rbfeeder");

    if (ret != 0) {
        log_level(8, "Ok, started! Pid is: %i\n", ret);
        p_dump = ret;
        sendStats();
    } else {
        log_level(8, "Error starting dump1090\n");
        p_dump = 0;
        sendStats();
    }

    return;
}

这是“停止”的代码:

void stopDump(void) {

    if (checkDumpRunning()) {
        log_level(3, "Dump is running, let's try to kill.\n");

        if (kill(p_dump, SIGKILL) == 0) {
            log_level(3,"Succesfull kill dump!\n");
            sendStats();
            return;
        } else {
            log_level(3,"Error killing dump.\n");
            return;
        }


    } else {
        log_level(3, "Dump is not running.\n");
    }

    return;
}

和run_cmd函数:

pid_t run_cmd(char *cmd) {
    pid_t pid, ret;
    char *argv[] = {"sh", "-c", cmd, NULL};
    int status, s;
    posix_spawn_file_actions_t file_actions;
    posix_spawn_file_actions_t *file_actionsp;

    s = posix_spawn_file_actions_init(&file_actions);
    if (s != 0)
        return 0;

    //STDERR_FILENO
    s = posix_spawn_file_actions_addclose(&file_actions,STDERR_FILENO);
    if (s != 0)
        return 0;

    file_actionsp = &file_actions;


    //printf("Run command: %s\n", cmd);
    status = posix_spawn(&pid, "/bin/sh", file_actionsp, NULL, argv, environ);
    if (status == 0) {
        log_level(8, "Child pid: %i\n", pid);
        ret = pid;
        /*        
        if (waitpid(pid, &status, 0) != -1) {
            printf("Child exited with status %i\n", status);
        } else {
            perror("waitpid");
        }
         */
    } else {
        //  printf("posix_spawn: %s\n", strerror(status));        
        ret = 0;
    }

    return ret;
    //printf("End of run\n");
}

p_dump 是一个保存 PID 的全局变量。

这张图片是当我的“客户”收到命令(通过以太网)启动外部程序时:

然后,同一台机器上的HTOP....看到PID相同,这意味着我的变量是正确的:

然后,我发送了一个“停止”命令,我的客户端执行了“stopDump”,但一个进程仍在运行(来自同一程序的其他线程被“杀死”):

外部程序本身不会“派生/分叉”,但它确实有线程。

【问题讨论】:

    标签: c linux


    【解决方案1】:

    您的杀戮成功完成,因为该进程正在变成僵尸,(HTOP 中状态列中的 Z)。僵尸进程在内核中仍有元数据,但实际上并未运行。为了摆脱僵尸,父母必须等待这个过程。由于您的进程是父进程,因此在 kill 成功后添加对 waitpid(p_dump) 的调用应该可以处理此问题。

    【讨论】:

    • 没有改变任何东西 :( if (kill(p_dump, SIGKILL) == 0) { waitpid(p_dump); airnav_log_level(3,"Succesfull kill dump!\n"); sendStats(); return; } else { airnav_log_level(3,"Error killing dump.\n"); return; }
    • @JonisMaurinCeará 你真的加了waitpid(p_dump);??? RTFM 因为它是 pid_t waitpid(pid_t pid, int *stat_loc, int options); 答案也需要修复。
    【解决方案2】:

    user1937198 的回答很好,但我找到了另一种不需要调用任何函数的方法,例如“waitpid”。

    struct sigaction sigchld_action = {
      .sa_handler = SIG_DFL,
      .sa_flags = SA_NOCLDWAIT
    };
    sigaction(SIGCHLD, &sigchld_action, NULL);
    

    至少在我的情况下,它可以防止杀死后的僵尸进程。效果很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-05
      • 1970-01-01
      • 2023-03-08
      • 2017-10-06
      • 2013-11-12
      • 2023-03-22
      • 2014-11-15
      • 2017-04-18
      相关资源
      最近更新 更多