如何检查 execl() 是否成功(多进程)
how to check if execl() is success (multiple process)
我通过 fork() 创建了多个子进程,并通过 execl() 让它们 运行 可执行文件。
我想检查是否有任何 execl() 失败(例如:尝试执行不存在的文件)。通过,尝试 execl() 所有程序,如果其中一个程序失败,则 return 1 before start communicates with any programs.
这里是参考代码,(假设所有设置都正确)
#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;
}
此程序仍向 "nonexist" 发送消息(但未按预期收到任何返回信息)。
有没有办法实现我的目标?谢谢!
你可以安排给child一个pipe()
的一端,设置为close-on-exec.
在 execl()
失败后(即如果调用 returns),child 将 write()
到管道。如果 parent 在其管道末端接收到任何东西(用 poll()
或类似的检查),那么它知道 child 失败了。
如果来自 child 的消息包含 child 的标识符,则管道可以在所有 children 之间共享。不过,尽量使 write()
足够小以使其成为原子!
实现您的目标的唯一可靠(但很奇特,可能不是很便携)的方法是使用 ptrace
。 parent 设置 PTRACE_TRACEEXEC
选项,在循环中分叉所有 children 和 wait()
。 child 确实
} else if () {
ptrace(PTRACE_TRACEME, ...);
execl(...);
}
parent 将继续循环 wait
直到所有 children 报告 PTRACE_EVENT_EXEC
或退出。在第一种情况下,exec
成功,child 停止。当您知道每个 child 已报告,并且您对它们的状态感到满意时,请对所有这些执行 ptrace(PTRACE_DETACH, ...)
并按需要继续。
我通过 fork() 创建了多个子进程,并通过 execl() 让它们 运行 可执行文件。
我想检查是否有任何 execl() 失败(例如:尝试执行不存在的文件)。通过,尝试 execl() 所有程序,如果其中一个程序失败,则 return 1 before start communicates with any programs.
这里是参考代码,(假设所有设置都正确)
#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;
}
此程序仍向 "nonexist" 发送消息(但未按预期收到任何返回信息)。
有没有办法实现我的目标?谢谢!
你可以安排给child一个pipe()
的一端,设置为close-on-exec.
在 execl()
失败后(即如果调用 returns),child 将 write()
到管道。如果 parent 在其管道末端接收到任何东西(用 poll()
或类似的检查),那么它知道 child 失败了。
如果来自 child 的消息包含 child 的标识符,则管道可以在所有 children 之间共享。不过,尽量使 write()
足够小以使其成为原子!
实现您的目标的唯一可靠(但很奇特,可能不是很便携)的方法是使用 ptrace
。 parent 设置 PTRACE_TRACEEXEC
选项,在循环中分叉所有 children 和 wait()
。 child 确实
} else if () {
ptrace(PTRACE_TRACEME, ...);
execl(...);
}
parent 将继续循环 wait
直到所有 children 报告 PTRACE_EVENT_EXEC
或退出。在第一种情况下,exec
成功,child 停止。当您知道每个 child 已报告,并且您对它们的状态感到满意时,请对所有这些执行 ptrace(PTRACE_DETACH, ...)
并按需要继续。