2016-11-04 21 views
3

のTerminateProcessのドキュメントは、部分的に、こう述べています。TerminateProcess(GetCurrentProcess()、exit_code)の後に待機が必要ですか?

This function stops execution of all threads within the process and requests 
cancellation of all pending I/O. 

... 

TerminateProcess is asynchronous; it initiates termination and returns 
immediately. If you need to be sure the process has terminated, call the 
WaitForSingleObject function with a handle to the process. 

これは、プロセスの自殺をのTerminateProcessを使用する場合は、このように、何が起こるかについて、いくつかのあいまいさを残し:

TerminateProcess(GetCurrentProcess(), exit_code) 

論理的には十分なものでなければならないこと、文書にはと記載されていますが、その後に処理が続行される可能性があります。不確定な状態になるバグのためにTerminateProcessを呼び出すと危険です。

私は待っオン自殺が必要とされていないことを確認することがわかっている最も近いものがで_invoke_watsonするソース・コードです:

C:\Program Files (x86)\Windows Kits\10\Source\10.0.10240.0\ucrt\misc\invalid_parameter.cpp 

この機能はありません最後のものは、それ自体でのTerminateProcessを呼び出すことである - と待ってはいけない。

確信を得ることは良いことであり、答えがドキュメントの補足として役立つように、ここで質問したかったのです。

+0

私は分かりませんが、あなたのプロセスがどれほど壊れていても、安全な側にあるためには、 'Sleep(INFINITE);の後に' TerminateProcess'を呼び出しても安全です。 –

+0

私は「ただ安全な側にいる」ということを嫌います。そのことは、単に安全のために配列に余分な要素を割り当てるというような醜さにつながります。私はむしろ文書化された保証を使用したいと思う。 しかし、あなたはサスペンダーと同様にベルトを置くことに本当の害がないということは間違いありません。 –

+0

私はTerminateProcess *がこの1つのケースでは同期的であるという疑いがあります(実際にはExitProcessが実際に行っていることを読んでいるようです)。しかし、誰かがそれを書いた文書を見つけることができなければ、文書化された契約。 :-) –

答えて

1

私はここに投稿しないことが好ましい誰かオフラインからこの答えを得た自分自身:

ユーザーモードマニュアルの私のテイクはのTerminateProcessは、一つのプロセスが別に行い、文書が書かれている一般的なものであるということですこの一般性のために、そしてこの意味では、正確で合理的である。

TerminateProcessには他のプロセスのハンドルを渡します。もちろん、継続的な操作のために呼び出しが返ってくることを願っています。

ドキュメントのポイントは、コールの成功とは、他のプロセスが終了したことを意味するものではなく、終了が正常に行われたということだけです。

これ以上のものに頼るなら、間違ったことをしているでしょう。したがって、正確に何が信頼できるものか、それについて考えることさえ調べることは、決して私にとって非常に有用ではないようです。私が気にしたように、私はTerminateProcessがあなたに他のプロセスを返し、すべてのスレッドがすでに終了しているとマークされていることを意味しています - 言い換えれば、ETHREADにTerminatedビットが設定されています。通常はI/Oの完了やキャンセルなどのために、APCの実行を継続します。この継続的な実行には大きな制約がありますが、不定期になることがあります。したがって、すべての実行が完了したことを知る必要がある場合は、プロセスが通知されるのを待ちます。

もちろん、別のプロセスを終了するためにTerminateProcessを呼び出すことは残酷なことです。ドキュメントでは、これもまた言います。

同じプロセス、独自のプロセスを終了させるのTerminateProcessを呼び出す

にはあまり残酷ではありません。 1つの例外を除いて、それは非常に最後の手段であり、そのコンテキストでさえ、本当に必死なものです。それを行う人は、呼び出しが戻ってくるよりも大きな問題が多くなければなりません。そうでなければ、明示的には返さないExitProcessを呼び出すことになります(プロセスはデッドロック状態になる可能性があります)。

TerminateProcessによる自動終了は、終了されるスレッドの1つが現在のスレッドである場合を導入します。Windows 7カーネルでは、PspTerminateThreadByPointer(PspTerminateThreadByPointerを参照してください)では、現在のスレッドのユーザーモード終了がAPCのキューイングではなくPspExitThreadに戻ります。最終出口。

私が読んでいるのは、ハンドルとして-1のTerminateProcessが返ってこないということですが、呼び出し元のスレッドで実行される最後の命令のカーネルにいた場合、プロセス内の他のスレッドまだAPCを処理するために実行されるかもしれませんが、あなたのAPCキューが排水されていて、戻ってくることは決してありません。実際、この時点でスレッドに何とかAPCが処理されていれば、カーネルのバグチェックが行われます。

ところで、残酷なTerminateProcessの例外は、NTDLLがExitProcessを介して比較的穏やかな自己終了であっても、本質的に最後のことです。確かによく知られていますが、RtlExitUserProcessを処理するためにNTDLLはNtTerminateProcess を2回、と呼びます。まず、ユーザーモードのクリーンアップとハンドルとしてNULLを与えるNtTerminateProcessへの呼び出しがあります。これが成功すると、より多くのユーザーモードクリーンアップがあり、NtTerminateProcessの呼び出しで終了し、ハンドルとして-1を与えます。

最後の呼び出しは、ハンドルとして-1を指定してTerminateProcessから取得したものです。 TerminateProcessを使用して自己終了すると、ユーザーモードとカーネルモードの両方で、ExitProcessから取得したクリーンアップをスキップするだけです。とにかく、TerminateProcessが実質的にExitProcessの終わりとしてNTDLLによって行われるとき、それは明らかに返さないと予想されます。

+0

私は、プロセス自体による完全なシャットダウンのCPU /ディスクコストを避けるために、Chromeの子プロセスを強制終了するためにTerminateProcess(GetCurrentProcess()、exit_code)を使用することをマイクロソフトの人々に推奨しました。これらの「クリーン」シャットダウンは、データがページアウトされると特に高価になります。 それは残忍なことですが、TerminateProcessで自殺することが推奨されるようです。 –

+0

ChromeでTerminateProcess(GetCurrentProcess()、exit_code)を使用して問題を継続しています。私たちのプロセスでは特定のサードパーティ製ソフトウェアを搭載したマシンでのみ返されます。追跡のバグはcrbug.com/820518です –

関連する問題