通过系统调用启动bash脚本的Linux C ++程序始终返回-1

时间:2013-08-05 20:49:19

标签: c++ linux bash system

我有一系列程序如下:

C ++程序“A”启动另一个C ++程序“B”,它启动一个bash脚本。

要启动bash脚本,我正在使用:

int returnVal = system("pathToScript/myScript.sh");

我可以在我的日志文件中看到脚本的输出,所以它肯定正在执行。

问题是,无论脚本返回什么,returnVal始终为-1。我甚至在脚本中硬编码了“exit 3”,当我通过系统调用启动它时,我仍然得到一个-1的returnVal。

在终端中独立运行脚本并回显“$?”显示预期的返回值为3。

那么当我通过一系列C ++程序运行它时,为什么退出代码会中断?有没有办法解决这个问题?

编辑 - 使用perror会显示“No child processes”错误消息。

编辑 - 作为替代方案,我正在尝试使用fork / exec / wait来执行我的脚本,但我得到随机退出代码,例如182,56,163,62, 51,等等......代码如下:

pid_t pid = vfork();

switch (pid)
{
  case -1:
     cout << "Failed to fork." << endl;

  case 0: // Child process
     cout << "Child process launched!" << endl;
     execl("/pathToScript/myScript.sh", "/pathToScript/myScript.sh", "someArgument", NULL);
     cout << "execl call failed." << endl;
     exit(0);

  default:
     int status;

     cout << "Waiting for process to complete..." << endl;

     waitpid(pid, &status, 0); // Wait for the process to complete.

     cout << "Process exited with status: " << WEXITSTATUS(status) << endl;
}

为什么我会在这里获得随机退出状态?

欣赏任何建议。谢谢!

1 个答案:

答案 0 :(得分:2)

正如评论中所提到的,你的问题是无视SIGCHLD。 忽略SIGCHLD可用于防止僵尸的创建。 因此,通过将其处置设置为默认,您可以破坏某些内容。

此处示例:

signal (SIGCHLD, SIG_DFL);
system ("some_program");
signal (SIGCHLD, SIG_IGN);

如果某个子进程(system中的子进程)在执行第一行和第三行之间终止,它将变为僵尸。

如果您想要正确解决此资源泄漏,您应该使用另一种方法(双forkwait)来解决僵尸问题。


  

为什么我会在这里获得随机退出状态?

由于waitpid来电失败。如果您打印出waitpid的返回值,则会-1errno的值最有可能是ECHILD。设置SIGCHLDSIG_IGN的处置会导致中断waitwaitpid。在您的示例中,waitpid不向status变量写入任何内容(或写入垃圾)。

  

182,56,163,62,51等。

此数字是未初始化的整数变量(或垃圾)的值。

  

作为替代方案,我正在尝试使用fork / exec / wait来执行我的脚本

这不是一个好的选择。替代解决方案是为程序的所有部分设置SIGCHLDSIG_DFL的处置。并改变其他部分处理僵尸的策略。