【问题标题】:why after the exit(0) is called, but the child process still remains?为什么在调用 exit(0) 之后,子进程仍然存在?
【发布时间】:2019-12-25 04:48:23
【问题描述】:

在父进程中我想启动一个守护进程来做长时间的工作,所以我使用 双 fork() 创建孙进程以启动守护进程。问题是 每隔一段时间,子进程不会成功退出,我确信 调用 exit(0) 之前的 printf(),但是当我使用“ps”时,我可以看到子进程 pid 列出,它永远不会退出。你知道为什么会这样吗,我应该调用 _exit(0) 而不是 exit(0) 让子进程退出?

startProcess(const char *pidfile, const char *command)
    pid_t   pid;
    char    cmd[1024];
    char    *head = cmd;
    char    *end;
    char    *argv[128] = {0};
    int     argc = 0;

    if( 0 == (pid=fork()) ) { //fork a child 
        if( 0 > setpriority(PRIO_PROCESS, 0, 0) ) {
            perror();
            return;
        }
        pid = fork(); //fork a grandchild
        if(-1 == pid){
            exit(-1);
        }else if(0 == pid){ //grandchild process
            if (snprintf(cmd, sizeof(cmd), "%s", command) <= sizeof(cmd) - 1) {
                /* change command line to argc/argv format */
                do {
                    if (argc >= sizeof(argv)/sizeof(argv[0]) - 1)
                        break;
                    for (; (*head == ' ' || *head == '\t'); head++); //remove space or TAB in the header
                    if (*head == '\0')
                        break;
                    if (NULL != (end = strpbrk(head, " \t"))) {
                        *end = '\0';
                        argv[argc++] = head;
                        head = end + 1;
                    } else {
                        argv[argc++] = head;
                        break;
                    }
                } while (1);
                argv[argc] = NULL; // Maximal value of argc is ARRAY_SIZE(argv) - 1.

                /* execute command to start a daemon*/
                execvp(argv[0], argv);
           }
           //should not enter here
           exit(-1);
        }else{ //still in child process
            printf("child process exit\n");
            exit(0); //child process exit, but sometimes this call seems fail
        }
    }else if(-1 == pid){
        return;
    }else{ //parent process
        int     status = 0;
        int     rv
        pid_t   r_pid = waitpid(pid, &status, WNOHANG);
        if (pid == r_pid) {
            if (WIFEXITED(status) && (0 == WEXITSTATUS(status))) {
                rv = 0;
            } else {
                rv = -1;
            }
        }
        return rv;
    }

【问题讨论】:

标签: c linux process fork exit


【解决方案1】:

使用WNOHANG 而不是0 肯定是错误的。如果父级在子级退出之前调用waitpid(使用WNOHANG),则子级将作为僵尸继续存在,等待被收割,直到父级也退出。

【讨论】:

  • 我以前在waitpid中使用“0”而不是WNOHANG,结果是父进程挂在waitpid,好像子进程没有触发SIG_CHLD到父进程,在其他字,exit(0) 没有成功调用。关键是子进程没有退出,不是子进程退出但没有被父进程收割
  • SIGCHLD 默认被忽略。如果你改变它,你就不能在信号处理程序之外使用waitpid
猜你喜欢
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 2021-11-26
相关资源
最近更新 更多