posix_spawn() :使用 posix_spawn() 时的错误处理问题
Posted
技术标签:
【中文标题】posix_spawn() :使用 posix_spawn() 时的错误处理问题【英文标题】:posix_spawn() : Problem with error handling when using posix_spawn() 【发布时间】:2020-10-28 11:00:36 【问题描述】:我正在尝试使用 posix_spawn() 创建一个新的子进程。 子进程启动后,调用者进程应该继续运行。
TLDR:为什么即使子可执行文件的路径无效(不存在),posix_spawn() 也会返回 0(成功)?在这种情况下以及 posix_spawn 实际失败但返回成功的任何其他情况下,如何正确检测错误?
我尝试了以下代码。
/* The CALLER process*/
int main(int argc, char *argv)
int status, pid;
printf("CALLER - Start\n");
char *args[] = "/home/<user>/child_exec", NULL;
status = posix_spawn(&pid, args[0], NULL, NULL, args, environ);
printf("Status: %d; PID: %d\n", status, pid);
printf("CALLER - End\n");
return 0;
/* The CHILD process */
int main()
printf("From CHILD\n");
return 0;
当我使用正确子可执行文件的路径运行调用程序时,它会按预期运行。 posix_spawn 的状态为 0,子进程的字符串被打印出来。
CALLER - Start
Status: 0; PID: 5110
CALLER - End
From CHILD
现在,当我使用无效的子可执行路径(例如 /home/user/child_exec123)运行同一程序时,即使子进程尚未执行,它仍然返回状态 0。
CALLER - Start
Status: 0; PID: 5251
CALLER - End
对于这种子路径不存在的情况,我可以在调用 posix_spawn() 之前检查文件是否存在。 但是,如果还有其他类似的错误,其中 posix_spawn() 实际失败但返回 0 怎么办?我如何发现是否有错误?
【问题讨论】:
奇怪的是 IBM 的 AIX 中的实现是理智的——它会在例如以下情况下返回失败。可执行文件不存在。我非常希望(对于 LINUX)最终不再需要克隆调用进程只是为了立即浪费结果。但出于某种我无法理解的原因,这仍然是 2021 年的标准做法! 【参考方案1】:来自手册页(特别是第二段):
RETURN VALUE
Upon successful completion, posix_spawn() and posix_spawnp() place the
PID of the child process in pid, and return 0. If there is an error
before or during the fork(2), then no child is created, the contents of
*pid are unspecified, and these functions return an error number as de‐
scribed below.
Even when these functions return a success status, the child process
may still fail for a plethora of reasons related to its pre-exec() ini‐
tialization. In addition, the exec(3) may fail. In all of these
cases, the child process will exit with the exit value of 127.
您需要使用wait*
函数之一来检查您的子进程的结果。无论如何,这将是一个好主意,否则你就会有一个僵尸。
【讨论】:
但是由于 wait* 函数正在阻塞调用,我怎样才能在子进程运行时继续运行调用者进程?我不想等待孩子完成,因为孩子可能需要很长时间才能完成。waitpid
接受选项。你要的是WNOHANG
。
谢谢。如果 posix_spawn() 返回的状态为 0,我只是尝试写这个:rc = waitpid(pid, &status, WNOHANG);
。但是即使子文件路径错误,waitpid 也会返回 0。如果我在调用 waitpid 之前睡了 2 秒钟,它会给出正确的错误。如何摆脱睡眠并仍然能够捕获错误?
您受调度程序的支配,因为无法保证您的子进程何时会尝试调用execve
。我不知道您可以等待的任何事件会告诉您进程已成功执行(SIGCHLD
会告诉您它已停止,但出于任何原因已停止)。
奇怪的是,IBM AIX 中的实现是正常的——它返回一个失败,例如可执行文件不存在。我非常希望(对于 LINUX)最终不再需要克隆调用进程并立即浪费结果。但出于某种我无法理解的原因,这仍然是 2021 年的标准做法!【参考方案2】:
posix_spawn
在子进程启动之前返回,将检测到不正确的路径。因此,子进程启动期间的任何错误,您只能通过其退出值来检查。
如documentation中所述:
返回值
Upon successful completion, posix_spawn() and posix_spawnp() place the PID of the child process in pid, and return 0. If there is an error during the fork() step, then no child is created, the contents of *pid are unspecified, and these functions return an error number as described below. Even when these functions return a success status, the child process may still fail for a plethora of reasons related to its pre-exec() initialization. In addition, the exec(3) may fail. In all of these cases, the child process will exit with the exit value of 127.
错误
The posix_spawn() and posix_spawnp() functions fail only in the case where the underlying fork(2), vfork(2) or clone(2) call fails; in these cases, these functions return an error number, which will be one of the errors described for fork(2), vfork(2) or clone(2). In addition, these functions fail if: ENOSYS Function not supported on this system.
【讨论】:
以上是关于posix_spawn() :使用 posix_spawn() 时的错误处理问题的主要内容,如果未能解决你的问题,请参考以下文章
解决 Sourcetree 报错 Couldn't posix_spawn: error 2 问题