web-dev-qa-db-ja.com

確認方法、どの制限を超えましたか? (ulimitのためにプロセスが終了しました。)

プロセスが無制限の環境で実行されると仮定します。

(
ulimit  ... -v ... -t ... -x 0 ...
./program
)

プログラムは終了します。

多くの理由が考えられます。メモリ/時間/ファイルの制限を超えています。単純なセグメンテーションフォルト。または戻りコード0での正常終了。

プログラムを変更せずに、プログラムが終了した理由を確認するにはどうすればよいですか?

追伸「バイナリが与えられたとき」という意味です。多分いくつかのラッパー(ptrace-ingなど)が役立つかもしれませんか?

11

一般的に言えば、残念ながらそうはならないでしょう。 (一部のオペレーティングシステムはそれを提供する場合がありますが、これをサポートしていることがわかっているオペレーティングシステムについては知りません。)

リソース制限のリファレンスドキュメント: getrlimit POSIX 2008から。

たとえば、CPUの制限_RLIMIT_CPU_を考えます。

  • プロセスがソフト制限を超えると、SIGXCPUが送信されます
  • プロセスがハード制限を超えると、プレーンSIGKILLが取得されます

プログラムでwait()を実行できる場合、SIGXCPUによってkillされたかどうかを確認できます。しかし、ハードリミットの違反のために派遣されたSIGKILLを、外部からの単純な古い殺害と区別することはできませんでした。さらに、プログラムがXCPUを処理する場合、外部からそれを確認することもできません。

_RLIMIT_FSIZE_についても同様です。プログラムが処理しない場合は、wait()ステータスからSIGXFSZを確認できます。しかし、ファイルサイズの制限を超えると、唯一発生するのは、その制限を再度テストしようとするI/Oが単にEFBIGを受け取るだけです。これはプログラムによって(または、残念ながら)処理されません。内部的に。プログラムが上記と同じようにSIGXFSZを処理する場合-あなたはそれについて知りません。

_RLIMIT_NOFILE_?まあ、あなたも信号を取得しません。 openや友達はEMFILEをプログラムに返すだけです。それ以外の場合は問題ありません。そのため、その状況で失敗するようにコーディングされた方法で失敗します(または失敗しません)。

_RLIMIT_STACK_?古き良きSIGSEGVは、配信される他の理由のスコアと区別できません。 (ただし、それがwaitステータスからプロセスを強制終了した理由です。)

_RLIMIT_AS_と_RLIMIT_DATA_は単にmalloc()を作成し、他のいくつかは失敗し始めます(または、スタックを拡張しようとしたときにAS制限に達した場合はSIGSEGVを受け取ります) Linux)。プログラムが非常によく書かれていない限り、おそらくその時点でかなりランダムに失敗するでしょう。

つまり、簡単に言えば、一般的に、失敗は他のプロセスの死の理由と視覚的に異なるわけではないため、確信が持てないか、プログラムから完全に処理することができます。外部から。

私が知る限り、あなたができる最善のことは、プログラムの分岐を待ってそれを待つ少しのコードを書くことです。

  • 終了ステータスをチェックして、SIGXCPUおよびSIGXFSZを検出します(AFAIK、これらの信号は、リソース制限の問題に対してOSによってのみ生成されます)。正確なニーズによっては、SIGKILLSIGSEGVもリソースの制限に関連していると考えることができますが、それは少しストレッチです。
  • 他の実装についてのヒントを得るために、実装でgetrusage(RUSAGE_CHILDREN,...)から何を得ることができるかを見てください。

ここで役立つOS固有の機能(LinuxではptraceやSolaris dtraceなど)、またはデバッガータイプの手法が存在する可能性がありますが、それはさらに特定の実装。


(私が完全に気づいていない魔法のことで他の誰かが答えてくれることを願っています。)

6
Mat

私は現在、同じ問題についていくつかの作業をしています。私はそれを部分的に解決することができました。 auditsusbsystemを使用しました。 [1]で作業を追跡できます。

[1] https://github.com/PaulDaviesC/Logging-limits.conf

3
PaulDaviesC