0

我最近移植了一个 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 造成干扰?

4

1 回答 1

0

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

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

于 2012-06-19T13:02:21.757 回答