从程序派生时的boost dataflow_exception

boost dataflow_exception when forked from program

本文关键字:dataflow exception boost 程序 派生      更新时间:2023-10-16

我最近移植了一个Qt应用程序,使用QTcpSockets而不是直接使用posix。我使用的渲染器有代码,如果视图应用程序还没有运行,可以通过分叉来启动它。对于我新重构的应用程序,如果在运行渲染器之前启动该应用程序,它似乎可以正常工作。然而,如果我在视图应用程序尚未运行的情况下启动渲染器,它将调用fork代码,程序通常会在渲染的中途崩溃。

Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt. You must
reimplement QApplication::notify() and catch all exceptions there.
terminate called after throwing an instance of '
boost::archive::iterators::dataflow_exception'
  what():  attempt to decode a value not in base64 char set

由于只有在使用fork()方法时才会抛出此异常,我想知道这是否是重构中的问题?我也相信只有当Qt应用程序从内部运行渲染器(启动查看器应用程序)时才会发生这种情况。当视图应用程序直接从渲染器分叉时,我看不到这个问题。我不确定fork()可能在做什么,从而导致这个异常。

int pid = fork();
if (pid != -1)
{
    if (!pid)
    {
        // Child process executes the following after forking.
    char arg1[] = "piqsl";
    char arg2[] = "-i";
    char arg3[] = "127.0.0.1";
    char* argv[4] = {arg1, arg2, arg3, NULL};
    // TODO: need to pass verbosity level for logginng
    signal(SIGHUP, SIG_IGN);
    nice(2);
    execvp("piqsl",argv);
...

重构后的查看器应用程序的唯一区别是它使用了QTcpSockets(和QTcpServer),现在链接到libQNetwork。这个库现在可能会对boost造成干扰吗?

问题是fork()创建了原始进程的精确副本,包括所有打开的文件句柄。Qt似乎使用了一些管道/套接字进行内部通信,由于这些管道/套接字与分叉进程中的管道/套接字相同,因此它们与原始进程冲突。

您可能会更幸运地使用exec()——据我所知,在分叉后没有办法安全地重新实例化QApplication。或者,如果您在创建QApplication之前分叉,它应该可以工作。