如何检查execl()是否成功(多个进程)

时间:2016-09-29 19:31:21

标签: c linux fork execl

我通过fork()创建了多个子进程,并让它们通过execl()运行可执行文件。

我想检查是否有任何execl()失败(例如:尝试执行不存在的文件)。通过,尝试execl()所有程序,如果其中一个失败,则在开始与任何程序通信之前返回1。

这里是参考代码,(假设所有设置都正确)

#DEFINE NUMBEROFCHILD 4
char** exeFile = {"./p1", "./p2", "./p3", "nonexist"); //"nonexist" is a non-exist program
int main(int argc, char** argv){
     pid_t childPID [numberOfChild];

     for (int i = 0; i<numberOfChild; i++) {
          //setting up pipes
          pid_t childPID[i] = fork();

          if(childPID[i] < 0) {
               //close all pipes and quit
          }else if (childPID[i] == 0) {
               //redirect pipe
               execl(exeFile[i],"args",(char*)0;
               return 1; 
               //I'm expecting this to return when it try to execute "nonexist"
               //but it didn't and keep running successed execl()
          }else {
               //close un-use pipes
          }
     }

     while(true) {
          for (int i = 0; i<numberOfChild; i++) {
               //communicate with childs through pipe
          }
     }

     for (int i = 0; i<numberOfChild; i++) {
          //close reminded pipes
          if (waitpid(childPID[i], NULL, 0) == -1){
               return 1;
          }
     }
     return 0;
}

此程序仍然向&#34; nonexist&#34;发送消息。 (但没有像预期的那样从中收到任何东西)。

反正有没有实现我的目标?谢谢!

2 个答案:

答案 0 :(得分:2)

你可以安排给孩子一个pipe()的一端,设置为关闭执行。

execl()失败后(即如果通话返回),孩子将write()到管道。如果父母在管道的末端收到任何东西(用poll()或类似物检查),那么它就知道孩子失败了。

如果来自子项的消息包含子项的标识符,则可以在所有子项之间共享管道。尽量保持write()小到足以成为原子的!

答案 1 :(得分:0)

实现目标的唯一强大(但非常奇特,可能不是非常便携)的方法是使用ptrace。父设置PTRACE_TRACEEXEC选项,分叉所有子项,并在循环中设置wait()。孩子没有

    } else if () {
        ptrace(PTRACE_TRACEME, ...);
        execl(...);
    }

父母应保持循环wait,直到所有孩子报告PTRACE_EVENT_EXEC或退出。在第一种情况下,exec成功,孩子停止了。当您知道每个孩子都报告了,并且您对他们的状态感到满意时,请对所有孩子进行ptrace(PTRACE_DETACH, ...)并按照需要继续进行。