4

waitpid私は、子プロセスを生成し、子プロセスの終了を待つように呼び出すプログラムを書いています。コードは以下のとおりです。

  // fork & exec the child
  pid_t pid = fork();
  if (pid == -1)
    // here is error handling code that is **not** triggered

  if (!pid)
    {
      // binary_invocation is an array of the child process program and its arguments
      execv(args.binary_invocation[0], (char * const*)args.binary_invocation);
      // here is some error handling code that is **not** triggered
    }
  else
    {
      int status = 0;
      pid_t res = waitpid(pid, &status, 0);

      // here I see pid_t being a positive integer > 0
      // and status being 11, which means WIFEXITED(status) is 0.
      // this triggers a warning in my programs output.
    }

waitpidの状態のマンページWIFEXITED:

WIFEXITED(status)
    returns  true  if  the child terminated normally, that is, by calling exit(3) or
    _exit(2), or by returning from main().

これは、成功時に整数 != 0 を返す必要があることを意味すると解釈しますが、これは私のプログラムの実行では発生していません。WIFEXITED(status) == 0

ただし、コマンド ラインから同じプログラムを実行すると$? == 0、gdb から開始すると、次のようになります。

[Inferior 1 (process 31934) exited normally]

プログラムは正常に動作しますが、トリガーされた警告を除いて、ここで何か他のことが起こっていると思わせます。

編集:
以下のコメントで提案されているように、子が segfault を介して終了したかどうかを確認し、実際にWIFSIGNALED(status)は 1 をWTERMSIG(status)返し、11を返しますSIGSEGV

私が理解していないのは、gdbまたはシェルを介した同じ呼び出しが成功するのに、execvを介した呼び出しがsegfaultで失敗するのはなぜですか?

EDIT2:
私のアプリケーションの動作は、子プロセスの動作、特に宣言された関数で子プロセスが書き込むファイルに大きく依存します__attribute__ ((destructor))waitpid呼び出しが返された後、このファイルは存在し、正しく生成されます。つまり、別のデストラクタのどこか、または私の制御外のどこかでセグメンテーション違反が発生します。

4

1 に答える 1

11

Unix および Linux システムでは、waitor waitpid(または他のwaitバリアントのいずれか) から返されるステータスは、次の構造を持ちます。

bits   meaning

0-6    signal number that caused child to exit,
       or 0177 if child stopped / continued
       or zero if child exited without a signal

 7     1 if core dumped, else 0

8-15   low 8 bits of value passed to _exit/exit or returned by main,
       or signal that caused child to stop/continue

(Posix はビットを定義せず、マクロのみを定義することに注意してください。ただし、これらは少なくとも Linux、Mac OS X/iOS、および Solaris で使用されるビット定義です。またwaitpidWUNTRACEDフラグとWCONTINUEDフラグを渡すと、continue イベントの場合)。

したがって、ステータス 11 は、シグナル 11 によって子プロセスが終了したことを意味しSIGSEGVます。

プログラムが無効な引数execv(C ライブラリ ラッパーexecveまたはその他のカーネル固有の呼び出し) を渡しているか、またはexecvシェルまたは gdb から実行したときと子の実行が異なっています。

をサポートするシステムを使用している場合はstrace、(親) プログラムを実行して、 がシグナルを引き起こしているstrace -fかどうかを確認します。execv

于 2014-04-24T14:47:55.800 に答える