繁体   English   中英

Linux fork / exec到同一目录下的应用程序

[英]Linux fork/exec to application in same directory

是否有一个exec变体将使用当前的应用程序目录来定位目标程序?

我正在使用C ++和Qt来实现“最后沟渠”错误报告系统。 使用Google Breakpad ,我可以创建一个minidump并将其直接执行到处理程序。 因为我的应用程序处于不稳定状态,所以我只想使用最小的依赖项来分叉并启动一个单独的错误处理过程。 错误报告应用程序将部署在与应用程序可执行文件相同的目录中。

我对forkexec选项很不熟悉,并且没有找到包含搜索路径中当前应用程序目录的exec选项。 这是我到目前为止:

static bool dumpCallback(const char* /*dump_path*/,
                         const char* /*minidump_id*/,
                         void* /*context*/,
                         bool succeeded)
{
  pid_t pid = fork();
  if (pid == 0)
  {
    // This is what I would *like* to work.
    const char* error_reporter_path = "error_reporter";

    // This works, but requires hard-coding the entire path, which seems lame,
    // and really isn't an option, given our deployment model.
    //
    // const char* error_reporter_path = "/path/to/app/error_reporter";

    // This also works, but I don't like the dependency on QApplication at this
    // point, since the application is unstable.
    //
    // const char* error_reporter_path =
    //     QString("%1/%2")
    //    .arg(QApplication::applicationDirPath())
    //    .arg("error_reporter").toLatin1().constData();

    execlp(error_reporter_path,
           error_reporter_path,
           (char *) 0);
  }
  return succeeded;
}

关于使用forkexec 最佳实践的任何其他建议也将受到赞赏; 这是我第一次使用它们。 我现在只关心Linux(Ubuntu,Fedora); 我稍后会处理其他操作系统的处理程序。

你要求的实际上很容易:

{
  pid_t pid = fork();
  if (pid == 0)
  {
    const char* error_reporter_path = "./error_reporter";
    execl(error_reporter_path,
          error_reporter_path,
          (char *) 0);
    _exit(127);
  }
  else
    return pid != -1;
}

但它没有做你想要的。 当前工作目录不一定与包含当前可执行文件目录相同 - 事实上,在几乎所有情况下,它都不会。

我建议你做的是使error_reporter_path成为一个全局变量,并使用你的“选项2”代码在main的最开始初始化它

     QString("%1/%2")
    .arg(QApplication::applicationDirPath())
    .arg("error_reporter").toLatin1().constData();

然后QString对象(不仅仅是它的constData )必须在程序的生命周期中存在,但这应该不是问题。 请注意,您应该转换为UTF-8,而不是Latin1(我猜QString使用宽字符?)

我认为你有两个选择:

  1. 添加'。' 到$ PATH。
  2. getcwd()的结果前置到可执行文件名。

您应该在程序启动时构建辅助程序可执行文件的路径,并将其保存在某个地方(在全局变量或静态变量中)。 如果您只需要在Linux上运行,可以通过读取/ proc / self / exe来获取可执行文件的位置。 像这样的东西:

// Locate helper binary next to the current binary.
char self_path[PATH_MAX];
if (readlink("/proc/self/exe", self_path, sizeof(self_path) - 1) == -1) {
  exit(1);
}
string helper_path(self_path);
size_t pos = helper_path.rfind('/');
if (pos == string::npos) {
  exit(1);
}
helper_path.erase(pos + 1);
helper_path += "helper";

摘自此处的完整工作示例: http//code.google.com/p/google-breakpad/source/browse/trunk/src/client/linux/minidump_writer/linux_dumper_unittest.cc#92

  1. 永远不会在任何情况下添加“。” $ PATH !!

  2. 如果你将getcwd()添加到可执行文件名(argv [0])中,那么在必须有机会更改当前工作目录之前,你必须做的是main中的第一件事。 然后,您必须考虑如何处理生成的文件名中的符号链接。 即便如此,您仍然无法确定argv [0]是否设置为用于执行程序的命令

选项3:

硬编码可执行文件中的完整文件名,但使用configure脚本设置文件名。 (您正在使用配置脚本,对吧?)

备选案文4;

不要叫exec。 您不必在fork之后调用exec。 只是假装你刚输入“main”,并在错误报告完成后调用“exit”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM