1

私のアプリケーションはサブプロセス プログラムを開始して、QuickTime フレームワークfork()とパイプを使用してビデオを読み取ります。サブプロセスは、ビジーでない場合、つまりusleep入力があるまで待ちループに入ります。サブプロセスは GUI アプリケーションではなく、C++ で記述されています。

MSVC コーデックを使用してコード化された AVI ビデオを開くと、アプリケーション アイコンの 2 つ目のコピーがドックに表示され、バウンスします。アクティビティ モニターで約 30 秒後に、CPU が ~0% のように見えても、サブプロセスが「応答していません」に変わることがわかります。サブプロセスはまだ実行中で、応答しています。アクティビティモニターが別のことを言っているだけです。

gdb attachサブプロセスの状態を見ると、その出力を介して確認するか、確認します。すべてがうまく見えます。サブプロセスに、ファイルを閉じて別のファイルを開いて引き続き使用するように指示できます。その時点で、跳ねるドック アイコンが消え、プロセスが応答なしとしてマークされなくなります。

OSX が私のサブプロセスがクラッシュした (?) と考えているようですが、例外を検出できません。

ドックにアイコンが表示され、バウンスし、応答していないとマークされているサブプロセスを停止するにはどうすればよいですか?

これは、サブプロセスとの通信をセットアップする方法です。

#include <unistd.h>

#define READ 0
#define WRITE 1

// Start process
pid_t popen2(const char *command, char * const argv[], int *infp, int *outfp)
{
  int p_stdin[2], p_stdout[2];
  pid_t pid;

  // Set up pipes
  if(pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
    return(-1);

  pid = fork();

  if(pid < 0)
    return(pid);
  else if(pid == 0)
  {
    // Set up communication via stdin/out
    close(p_stdin[WRITE]);
    dup2(p_stdin[READ], READ);
    close(p_stdout[READ]);
    dup2(p_stdout[WRITE], WRITE);

    execvp(command, argv); // run subprocess
    perror("execvp");

    exit(1);
  }

  // Provide pointers to the file descriptors to the caller
  if(infp == NULL)
    close(p_stdin[WRITE]);
  else
    *infp = p_stdin[WRITE];

  if(outfp == NULL)
    close(p_stdout[READ]);
  else
    *outfp = p_stdout[READ];

  return(pid);
}

の詳細については、この SO の質問を参照してくださいpopen2()

:このコードが問題の原因である場合とそうでない場合があります。第一段階として、何が原因なのかを突き止めたいと思います。

4

3 に答える 3

3

「応答しない」部分は単純です。サブプロセスはどのタイプのランループも実行していないため、システムの POV からは、イベントを処理していません。

新しいプロセスがドック アイコンを取得する理由については少し曖昧ですが、基本的にfork()は、親プロセス (この場合はフォアグラウンド アプリケーション) の属性を継承するプロセスを作成することになります。OS X には、より賢明な方法でサブプロセスを起動する多くのメカニズムがありますfork()。アプリが Cocoa にある場合は を使用しNSTask、それ以外の場合は を参照してくださいposix_spawn(2)

これは、ルーチンの代わりにドロップする必要があります。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <spawn.h>
#include <signal.h>
#include <crt_externs.h>

#define READ 0
#define WRITE 1
#define environ (*_NSGetEnviron())

pid_t popen2(const char *command, char * const argv[], int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if(pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return(-1);

    posix_spawn_file_actions_t file_actions;
    posix_spawn_file_actions_init(&file_actions);
    posix_spawn_file_actions_adddup2(&file_actions, p_stdin[READ], 0);
    posix_spawn_file_actions_adddup2(&file_actions, p_stdout[WRITE], 1);
    posix_spawn_file_actions_adddup2(&file_actions, 2, 2);

    posix_spawnattr_t spawnAttributes;

    posix_spawnattr_init(&spawnAttributes);
    sigset_t no_signals;
    sigset_t all_signals;
    sigemptyset (&no_signals);
    sigfillset (&all_signals);
    posix_spawnattr_setsigmask(&spawnAttributes, &no_signals);
    posix_spawnattr_setsigdefault(&spawnAttributes, &all_signals);
    short flags = POSIX_SPAWN_CLOEXEC_DEFAULT | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
    posix_spawnattr_setflags(&spawnAttributes, flags);

    if (posix_spawn(&pid, command, &file_actions, &spawnAttributes, argv, environ)) {
        perror("posix_spawn");

        exit(1);
    }

    close(p_stdin[READ]);
    if(infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    close(p_stdout[WRITE]);
    if(outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return(pid);
}
于 2013-06-22T11:10:55.010 に答える
0

サブプロセスを MacOS XPC サービスとして書き直すことになりました。XPC サービスのプロパティ リストに LSBackgroundOnly を追加して、Launch Services がシステム イベント処理を無視するようにしました。

于 2014-02-07T23:48:34.093 に答える
0

c++11 をサポートするコンパイラを使用している場合は、packaged_tasksを確認することをお勧めします。

または、 condition_variablesを使用することもできますが、最初にパッケージ化されたタスクで動作するようにします。条件変数は、高レベルのパッケージ化されたタスクよりも原始的です。いずれにせよ、従来の IPC 手法よりもこれらのメカニズムを使用する方がはるかに簡単です (そして標準に準拠しています)。

もちろん、別のプロセスを用意する必要がない場合です。

詳細については、The C++ Programming Language, 4th Editionを確認することを強くお勧めします。これには、あなたに適した単純なベクトルを使用した生産者/消費者メカニズムの簡単な例があります。この本を読みたくない場合は、condition_variablesfutures、またはpromisesを使用するための同様の例をオンラインで見つけることができると確信しています。

HTH

于 2013-06-28T04:14:33.480 に答える