0

最近、posix の代わりに QTcpSockets を使用するように Qt アプリを移植しました。私が使用しているレンダラーには、まだ実行されていない場合に分岐してビュー アプリを起動するコードがあります。新しくリファクタリングされたアプリでは、レンダラーを実行する前にアプリを起動すると問題なく動作するようです。ただし、ビュー アプリがまだ実行されていない状態でレンダラーを起動すると、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 にリンクするようになったことです。このライブラリはおそらくブーストで干渉を引き起こしていますか?

4

1 に答える 1

0

問題は、 fork() が、開いているすべてのファイル ハンドルを含む元のプロセスの正確なコピーを作成することです。Qt は内部通信にいくつかのパイプ/ソケットを使用しているようですが、これらはフォークされたプロセスの同じパイプ/ソケットであるため、元のプロセスと競合します。

代わりに exec() を使用すると、おそらく運が良くなるでしょう。私の知る限り、フォーク後に QApplication を安全に再インスタンス化する方法はありません。または、QApplication を作成する前にfork すると機能するはずです。

于 2012-06-19T13:02:21.757 に答える