psを実行すると競合状態が発生する危険はありますか?

psを実行すると競合状態が発生する危険はありますか?

長期実行プロセス(Javaで時々関連する)を起動し、デフォルトpsで次のことを試みます。

Process longRunningProcess = new ProcessBuilder(...).start();

Process psProcess = new ProcessBuilder("ps").start();
psProcess.waitFor();
// extract the PID from the output of psProcess

またはBashでも同様です。

$ long_running_process > /dev/null & ps

問題は、長期実行プロセスがpsまだ報告されていないまだ開始中の状態にある可能性があることです。それとも、実行時にps長期実行プロセスが目に見えるほどに開始されるという保証はありますか?コマンドを繰り返し実行現れるプロセスは常に含まれますが、これは明らかに何も証明しません。

この記事実行されたコマンドに対して可能な競合状態に関する警告後ろに psが開始されたが(たとえばps | grep)、以前に開始されたプロセスについては何も言及しませんps

答え1

OpenJDKと同じタスクの場合v6-b14、PID〜するps仮想ファイルシステムをスキャンするときに使用できます/proc。プロセスが実際に開始されたか(つまり、何も完了したかどうか)はっきりわかる方法はありません。 PIDが予約されて予約されただけです。死んだそしてゾンビの状態)。

ただし、psUnixシステムにロックされているため、Reflectionを使用してProcessBuilderから返されたオブジェクトを調べることができます。これはUnixProcessに接続します。

final class  [More ...] UNIXProcess extends Process {
    private FileDescriptor stdin_fd;
    private FileDescriptor stdout_fd;
    private FileDescriptor stderr_fd;
    private int pid; <----------------------------------------------
    private int exitcode;

もちろんはいハッキングですが、生成と大きく変わらず、間違いなくps高速です。それほど危険ではありません。pid「Change Soon」というpidフィールドは表示されません。

答え2

私はJavaに慣れていませんが、ProcessBuilder.startそれが返されると何かが始まったでしょう。既存のスレッド内でコールバックを設定し、後でそれを実行して子プロセスを作成したり、同じプロセスで別のスレッドを起動して最終的に子プロセスを作成したり、子プロセスを作成したりすることもできforkます。正しい結果を得ることはより難しいので、最初の2つのうちの1つであると疑われます。子プロセスと通信したり、その状態を取得したりするメカニズムを含む、子プロセスへの参照は、そのプロセスが作成されるのを待つ必要があります。

したがって、ProcessBuilder.start返されると、プロセスが作成されたことを確認できます。しかし、これは競争条件が存在しないという意味ではありません。プロセスが開始された直後に終了または競合する場合は、ユーザーが表示したときにそのプロセスが終了した可能性があります。プロセスIDは、親プロセスが次のいずれかを呼び出すまで保持されます。waitシステムコールシリーズ;プロセスが終了すると、そのプロセスがプロセスである限り、PIDは有効になります。ゾンビつまり、親が電話しない限りwait

したがって、プロセスIDが有効であることを確認する唯一の方法は、親プロセスと調整して、親プロセスが呼び出されたがまだ呼び出されていないことを確認するforkことですwait

答え3

私は過去にこの問題に直面していました。私は以下を実行して問題を解決しました。

exec java WhateverTheClassNameIs -p $$

ここで、「-p」は、「私のPIDはこのフラグの値です」を意味するフラグです。main()その部分をJavaメソッドでコーディングする必要があります。

exec基本要素はシェル自体を介してロードされるため、これはシェルスクリプトの最後の行でなければなりません。javaプログラムの終了状態はWhateverTheClassNameIsもはや実際には存在しないため、シェルの終了状態ではなく終了状態になります。これによりコードがいくつか歪む可能性がありますが、PIDをJavaプログラムに入れるより良い方法が見つかりません。

関連情報