2017-04-19 54 views
1

前些日子,我问here如何在不使用fork()的情况下使用C启动程序。这个解决方案工作正常.....除了我不能杀死这个子进程! 我的程序(在这种情况下,'rbfeeder')有一些线程....当我发送kill信号时,只有线程被杀死(我认为)。我究竟做错了什么?无法杀死以spawn开头的PID

这是用来 '开始' 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的全局变量。

该图像是当我的“客户”接收命令(以太网),以启动外部程序:

enter image description here

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

enter image description here

然后,我已经发了“停止”命令,我的客户端执行“stopDump”,而是一个过程仍在运行(从同一程序的其他线程AR E '杀'):

enter image description here

外部程序不 '重生/叉' 本身,但它确实有螺纹。

回答

0

user1937198的回答很好,但我发现了另一种不需要调用任何函数的方法,如'waitpid'。

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

至少在我的情况下,它是在杀死后阻止僵尸进程。它工作正常。

3

你的kill成功完成,因为进程正在变成僵尸(在HTOP状态栏中的Z)。僵尸是一个在内核中仍然具有元数据的进程,但实际上并没有运行。为了摆脱僵尸,父母必须等待这个过程。由于你的进程是父进程,杀死成功后向waitpid(p_dump)添加一个调用应该可以解决这个问题。

+0

不会改变任何东西:('''如果(杀死(p_dump,SIGKILL)== 0){ waitpid函数(p_dump); airnav_log_level(3, “Succesfull杀转储\ n!”); sendStats( ); 回报; }其他{ airnav_log_level(3, “错误杀人转储\ n”); 回报; }''' –

+0

@JonisMaurinCeará你真的加上'waitpid函数(p_dump);'??? [ RTFM](http://man7.org/linux/man-pages/man3/wait.3p.html),因为它的'pid_t waitpid(pid_t pid,int * stat_loc,int options);'答案也需要修正。 –