execv 和 fork:通知父子进程执行文件失败
execv and fork: inform parent that child failed to execute the file
主进程如何知道子进程执行文件失败(例如没有那个文件或目录)?例如,在下面的代码中,我们如何让 运行() 变成 return 不是 0 的值?谢谢!
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
enum ErrorType { noError, immediateFailure, returnFailure, forkFailure };
using namespace std;
int run(void)
{
int error = noError;
//char proc[] = "/bin/uname";
char proc[] = "/usr/bin/Idontexist";
char *const params[] = {proc, NULL};
pid_t pid = fork();
printf("pid = %d\n",pid);
if (pid == 0)
{
if ( execv(proc,params)==-1 )
{
error = immediateFailure;
}
printf("child: error = %d\n",error);
}
else if (pid > 0)
{
/* This is the parent process
* incase you want to do something
* like wait for the child process to finish
*/
int waitError;
waitpid(pid, &waitError, 0);
if ( waitError )
error = returnFailure;
printf("parent: error = %d, waitError = %d\n",error,waitError);
}
else
{
error = forkFailure;
}
return error;
}
int main(void)
{
printf("run() = %d\n",run());
return 0;
}
输出:
pid = 4286
pid = 0
child: error = 1
run() = 1
parent: error = 0, waitError = 0
run() = 0
问题是execv
失败后的错误处理。 child 将 error
设置为 immediateFailure
,将 return 设置为 main
。然后 main
打印错误号,然后 returns 0
。但是0
表示成功,所以parent进程认为child成功了。
解决方法是return来自main
的错误号,或者在child代码中调用exit
,例如
if (pid == 0)
{
execv(proc,params);
error = immediateFailure;
printf("child: error = %d\n",error);
exit( error );
}
请注意,您不需要检查 execv
的 return 值,因为 execv
如果成功则不会 return。它只会 return 如果失败,并且总是 return -1.
您需要 return 来自 main
的错误代码,或 exit()
的值。现在,在所有情况下,您都从 main
return
ing 0
,这将是父级从 waitpid
.[=26= 收到的子级的退出代码]
最好的解决方法是在子进程中添加_exit(error)
:
printf("child: error = %d\n",error);
_exit(error);
在任何情况下都使用整数常量而不是随机枚举常量枚举。 1 和 2 是来自许多 unix 命令的常见 return 值,其中 1 表示命令不成功(例如 grep
未找到任何匹配项),2+ 表示命令确实失败(错误的论点等)`.
bash
、zsh
和其他 shell 使用 127
作为退出代码来表示 command not found / not 运行nable;因此建议这样做:
#define COMMAND_NOT_RUNNABLE 127
/* ... */
execv(proc, params); // exec never returns if successful.
perror(proc);
_exit(COMMAND_NOT_RUNNABLE);
在子进程中使用 _exit
的原因是它不会刷新 stdio 缓冲区(它也存在于父进程中)并且它不会 运行 atexit
个钩子。 (感谢Andrew Henle)
除了提议的 exit(error);
之外,您还应该为 waitpid
提供具体选项。在我将调用更改为 waitpid(pid, &waitError, WUNTRACED | WCONTINUED);
之前,您的代码对我不起作用
在我的例子中 exit(EXIT_FAILURE)
不会导致子进程的 return 到 waitpid() EXIT_FAILURE
状态,总是 0
。我的解决方案是abort()
子进程如果execv()
/execve()
执行失败
主进程如何知道子进程执行文件失败(例如没有那个文件或目录)?例如,在下面的代码中,我们如何让 运行() 变成 return 不是 0 的值?谢谢!
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
enum ErrorType { noError, immediateFailure, returnFailure, forkFailure };
using namespace std;
int run(void)
{
int error = noError;
//char proc[] = "/bin/uname";
char proc[] = "/usr/bin/Idontexist";
char *const params[] = {proc, NULL};
pid_t pid = fork();
printf("pid = %d\n",pid);
if (pid == 0)
{
if ( execv(proc,params)==-1 )
{
error = immediateFailure;
}
printf("child: error = %d\n",error);
}
else if (pid > 0)
{
/* This is the parent process
* incase you want to do something
* like wait for the child process to finish
*/
int waitError;
waitpid(pid, &waitError, 0);
if ( waitError )
error = returnFailure;
printf("parent: error = %d, waitError = %d\n",error,waitError);
}
else
{
error = forkFailure;
}
return error;
}
int main(void)
{
printf("run() = %d\n",run());
return 0;
}
输出:
pid = 4286
pid = 0
child: error = 1
run() = 1
parent: error = 0, waitError = 0
run() = 0
问题是execv
失败后的错误处理。 child 将 error
设置为 immediateFailure
,将 return 设置为 main
。然后 main
打印错误号,然后 returns 0
。但是0
表示成功,所以parent进程认为child成功了。
解决方法是return来自main
的错误号,或者在child代码中调用exit
,例如
if (pid == 0)
{
execv(proc,params);
error = immediateFailure;
printf("child: error = %d\n",error);
exit( error );
}
请注意,您不需要检查 execv
的 return 值,因为 execv
如果成功则不会 return。它只会 return 如果失败,并且总是 return -1.
您需要 return 来自 main
的错误代码,或 exit()
的值。现在,在所有情况下,您都从 main
return
ing 0
,这将是父级从 waitpid
.[=26= 收到的子级的退出代码]
最好的解决方法是在子进程中添加_exit(error)
:
printf("child: error = %d\n",error);
_exit(error);
在任何情况下都使用整数常量而不是随机枚举常量枚举。 1 和 2 是来自许多 unix 命令的常见 return 值,其中 1 表示命令不成功(例如 grep
未找到任何匹配项),2+ 表示命令确实失败(错误的论点等)`.
bash
、zsh
和其他 shell 使用 127
作为退出代码来表示 command not found / not 运行nable;因此建议这样做:
#define COMMAND_NOT_RUNNABLE 127
/* ... */
execv(proc, params); // exec never returns if successful.
perror(proc);
_exit(COMMAND_NOT_RUNNABLE);
在子进程中使用 _exit
的原因是它不会刷新 stdio 缓冲区(它也存在于父进程中)并且它不会 运行 atexit
个钩子。 (感谢Andrew Henle)
除了提议的 exit(error);
之外,您还应该为 waitpid
提供具体选项。在我将调用更改为 waitpid(pid, &waitError, WUNTRACED | WCONTINUED);
在我的例子中 exit(EXIT_FAILURE)
不会导致子进程的 return 到 waitpid() EXIT_FAILURE
状态,总是 0
。我的解决方案是abort()
子进程如果execv()
/execve()
执行失败