从未退出

时间:2016-01-04 09:50:15

标签: c process exec fork job-scheduling

我需要找到一种从execl命令获取状态的方法。我调用execl来获取需要作为守护进程(后台进程)运行的进程,该进程将由init进程继承。但是,即使execl调用本身没有失败,我尝试execl的进程也可能会退出。因此,execl成功运行并且不会返回到父代码,但是我尝试执行的进程可能会异常退出。我从主进程中分叉两次,在孙进程中运行execl,根据将由主进程捕获的孙子的状态退出子进程,并将成功或失败返回给调用者。

问题在于,在子进程(execl'ed进程的父进程)中我不能使用没有WNOHANG的waitpid,否则如果execl'ed进程没有退出,它会永远等待,另一方面我不能使用与WNOHANG一起,因为如果子进程在孙子(调用execl)之前被调度,它只会说孙子没有被退出(这是我的应用程序中的成功案例),即使孙子可能在execl执行后异常退出。

我试图使用管道,但我认为它不起作用。 (在管道写入之后的上下文切换,在execl或多核调度之前会再次破坏所有内容)我在这里附加代码段,这与我尝试使用的类似。可以请你帮我解决这个问题吗?感谢。

 int pid;
    pid = fork();
    const char* command_cstr = "pwd";  // this is only a placeholder.
    if ( pid < 0 ) {
            return -1;
    }
    if ( pid == 0 ) {  // CHILD CODE
            int fd[2];
            int val;
            setsid();  
            pipe(fd);
            pid = fork();
            if ( pid < 0 ) {
                    exit(1);
            }
            if ( pid == 0 ) {  // GRANDCHILD CODE
                    close(fd[0]);
                    val = 1;
                    write(fd[1], &val, sizeof(val));
                    close(fd[1]);
                    execl("/bin/bash", "bash", "-c", command_cstr, NULL);
                    exit(1);  // exits only when execl returns on error
            }
            // CHILD CODE
            // wait until grandchild process is executed
            close(fd[1]);
            read(fd[0], &val, sizeof(val));  // blocks until child writes
            close(fd[0]);
            int grandchild_status;
            waitpid(pid, &grandchild_status, WNOHANG);
            if (WIFEXITED(grandchild_status) == false) {
                    exit(0); // success case, execl alive
            } else {
                    exit(1);  // fail case, execl exitted
            }
    }
    // PARENT CODE
    // Reap the child, leaving the grandchild to be inherited by init
    int child_status;
    waitpid(pid, &child_status, 0);
    // If the child exited with 0, it managed to fork and execl didn't exit
    if (WIFEXITED(child_status) && WEXITSTATUS(child_status) == 0) {
            // Child forked and exited successfully
            return 0;
    } else {
            // If the child did not exit with 0 
            return -1;
    }
 }

0 个答案:

没有答案