自分のプログラムにシグナルハンドラが登録されています。望ましくないシグナル(SIGABRT)を受信すると、シグナルハンドラで 'exit(-1)'を呼び出してプロセスを終了します。しかし、いくつかの事件で気づいたように、exit()を呼び出しますが、プロセスを終了させることはできません。exit()はプロセスの終了に失敗しますか?
問題はランダムに生成され、exit()の実行が強く疑われます。
exit()がプロセスを終了できない理由や場合がありますか。
ありがとうございました。
自分のプログラムにシグナルハンドラが登録されています。望ましくないシグナル(SIGABRT)を受信すると、シグナルハンドラで 'exit(-1)'を呼び出してプロセスを終了します。しかし、いくつかの事件で気づいたように、exit()を呼び出しますが、プロセスを終了させることはできません。exit()はプロセスの終了に失敗しますか?
問題はランダムに生成され、exit()の実行が強く疑われます。
exit()がプロセスを終了できない理由や場合がありますか。
ありがとうございました。
exit()
をシグナルハンドラから呼び出していますか?あなたはシグナルハンドラから呼び出されたときに動作することが保証されているすべての機能を見ることができます
man 7 signal
で
、セクション非同期シグナル安全機能:
は、シグナルハンドラ関数があるため、非常に慎重でなければなりません他の場所での処理は、プログラムの実行中の何らかの任意の点である で中断される可能性があります。 POSIXには「安全な機能」という概念があります。 信号が安全でない関数の実行を中断し、ハンドラが安全でない関数を呼び出す場合、 プログラムの動作は未定義です。あなたはそこ
ことができます。
(もPOSIX.1-2001技術正誤表2として知られている)POSIX.1-2004は、以下の機能が安全にシグナルハンドラ内で呼び出すことができることを保証 に実装が必要機能_Exit()
、_exit()
、およびabort()
を参照してください。ただし、exit()
は特にありません。したがって、シグナルハンドラから呼び出すべきではありません。
シグナルハンドラ(printf()
?)から安全でない関数を呼び出しても、ほとんどの時間は動作しますが、常にそうとは限りません。
シグナルハンドラから非同期シグナルが安全でない関数を呼び出すことは、シグナルが別の非同期シグナルが安全でない関数を中断しない限り、完全に有効です*。これは「ほとんどの場合」動作する理由を説明しますが、シグナルハンドラが安全でないものを中断できないように注意する場合は、シグナルハンドラで非同期シグナルが安全でない関数を使用することもできます(例えば、シグナルをほとんどマスクしたままにし、ファイルディスクリプタIOや 'select'のような純粋な算術演算や非同期シグナル安全なライブラリ呼び出しを実行している間はブロックを解除するだけです)。 –
@R ..あなたはもちろんです。しかし、実際には、非常に特殊な場合を除いて、それを確実にすることは困難です。私は個人的には、安全でない機能をすべて一緒に避けるために便利です。 – rodrigo
も参照してください:http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html –
はい、のようないくつかの状況がある:
が出口()関数は、最初の関数が呼び出されることを除いて、それらの登録の逆順でのatexitにより登録されたすべての機能()をコールしなければなりませんそれが登録された時点ですでに呼び出されていた以前に登録された関数の後各関数は、登録された回数だけ呼び出されます。そのような関数の呼び出し中に、登録された関数への呼び出しを終了するlongjmp()関数の呼び出しが行われた場合、その動作は未定義です。
atexit()の呼び出しによって登録された関数が返されなかった場合、残りの登録された関数は呼び出されず、残りのexit()処理は完了しません。 exit()が複数回呼び出された場合の動作は未定義です。
exitのPOSIXページを参照してください。
詳細については、状況に応じてデバッガを接続し、コールスタックを確認してください。
私はバグの別の原因を 'exit'のような関数よりも探すことをお勧めします。ほとんどの場合、コンパイラや標準ライブラリなどにバグがあると思うと、間違いが原因でエラーが発生します。 – Shahbaz
@Shahbaz:Mandarは、実装のバグについて尋ねることも、存在することを示唆することもありません。問題は、プログラムを常に終了させるために 'exit'が指定されているかどうかです。答えはnoです(特に、シグナルハンドラから呼び出された場合はそうではありません)。 –
SIGABRTのハンドラをexit()に設定するだけではどうですか?シグナルハンドラで何をしているのかは、atexit()コールで行います。 –