none
WaitForMultipleObjects関数のハンドルリークについて RRS feed

  • 質問

  • いつもお世話になっております、yanazakiと申します。

    以下の現象が発生し、難儀しております。

    原因等、お心当たりのある方が
    いらっしゃいましたら、ご教授お願いできますでしょうか。

    ------
    C++のプログラムにて、以下機能を作成しています。
     (1)親スレッドから、子スレッドを3つ呼び出す
     (2)WaitForMultipleObjects関数で子プロセス群を監視し、
      子スレッド停止を判断するため、シグナル受信まちをしている。
      タイムアウトは30秒
     (3)(2)の処理を定周期でループする。

    この処理で、子スレッドは停止していないにもかかわらず、
    作成したプログラムのHandle Count が不定期に増加していきます。

    MicrosoftのツールProcessExplorerで見ますと、
    Typeが「Event」で、名前が空白のハンドルが増殖しているようです。

    WaitForMultipleObjectsを実行すると、ハンドル数が
    増加する、というようなことはありませんでしょうか。


    OSは、WindowsServer2008R2 ,開発環境は、VisualStuido2013です。
    わかりずらい質問で申し訳ありませんが、
    何卒よろしくお願い申し上げます。

    以上

    2017年3月10日 6:48

回答

  • > WaitForMultipleObjectsを実行すると、ハンドル数が
    > 増加する、というようなことはありませんでしょうか。

    あり得ないと思います。
    「Handle Count が増加する」ということは、ファイル、イベント、セマフォ、スレッドなど何らかのオブジェクトが生成されたことを示すものであって、増加自体が必ずしも問題となる訳ではないのでは?
    そもそも Hanlde は、ご自身が作成したコードだけで生成される訳ではありません。
    ご自身のプログラムが発行した API コールのその先、例えば kernel32.dll / kernelbase.dll 内でそれら DLL が何かのオブジェクトを生成するケースは、頻繁にあります。
    さらに言えば、イベントのハンドル数が増えるということは、別の (異なる) イベント オブジェクトが新たに生成されたことを意味するだけで、それ自体が WaitForMultipleObjects() API の挙動と直接結び付いている訳ではありません。
    (そのハンドルを WaitForMultipleObjects() API のパラメータとして指定しない限り、この API の挙動に影響を与えることはない。)

    SysInternals では GUI ベースの "ProcessExplorer" 以外にも、コンソール ベースの "Hanle" というツールも提供しています。
    -------------------------------------------------
    Handle
    https://technet.microsoft.com/ja-jp/sysinternals/handle.aspx
    -------------------------------------------------
    "Handle" ツールでは、任意のタイミングでのスナップ ショットを採取することが可能ですので、イベント ハンドルが本当に増殖しているのか、きちんと確認されることをお勧めします。
    (もっとも「名前なしイベント」は、どのプロセスでも結構大量に生成されているので、それ自体が問題になるとは、個人的には思いませんが。。。)
    • 回答としてマーク yanazaki 2017年3月12日 23:32
    2017年3月10日 8:43
  • 「当方のプログラムソースでは、ハンドルの解放は行われているにもかかわらず」というのは、きちんとライブ デバッグあるいはダンプ ファイルの解析で確認されたことなのでしょうか?
    (「机上デバッグ」での見落としは常に有りうることで、一番大切なのは、「事実」として起きていいることをきちんと把握することだと思います。)

    あなたのプログラム ソースに不備があるから、ハンドル リークが起きているのでは?
    (本当にハンドル リークが起きているのかは、この質問の文面ではわかりませんが。。。)
    もしそのハンドル リークが kernel32.dll 等のマイクロソフト社が提供するシステム コンポーネント側の問題と仮定した場合、それは全ての Windows アプリケーションで起きる可能性がある、起きてもおかしくない。。。ということになりますよね?

    「サーバ再起動などの運用回避で対応」しているのであれば、そのタイミングで一度「完全メモリ ダンプ」を採取して解析してみては?
    自分でダンプ解析できないのであれば、マイクロソフトにお願いすれば、「有償」で解析してくれると思います。(ここでまた「ダンプ解析云々」というと、またアカウント削除されてしまうかもしれないので、これ以上は言及しませんけど。)

    個人的には。。。
    そのサーバー環境に "WinDBG" をインストールさせてもらって、問題アプリのプロセスに WinDBG からアタッチし、"!htrace" コマンドでどのスレッドがなんのハンドルをオープンしているのか、その差異をきちんとチェックすれば、原因を特定できるのは。。。と思っています。
    --------------------------------------------------
    !htrace
    https://msdn.microsoft.com/en-us/library/windows/hardware/ff563208%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
    --------------------------------------------------

    2017年3月13日 2:54

すべての返信

  • > WaitForMultipleObjectsを実行すると、ハンドル数が
    > 増加する、というようなことはありませんでしょうか。

    あり得ないと思います。
    「Handle Count が増加する」ということは、ファイル、イベント、セマフォ、スレッドなど何らかのオブジェクトが生成されたことを示すものであって、増加自体が必ずしも問題となる訳ではないのでは?
    そもそも Hanlde は、ご自身が作成したコードだけで生成される訳ではありません。
    ご自身のプログラムが発行した API コールのその先、例えば kernel32.dll / kernelbase.dll 内でそれら DLL が何かのオブジェクトを生成するケースは、頻繁にあります。
    さらに言えば、イベントのハンドル数が増えるということは、別の (異なる) イベント オブジェクトが新たに生成されたことを意味するだけで、それ自体が WaitForMultipleObjects() API の挙動と直接結び付いている訳ではありません。
    (そのハンドルを WaitForMultipleObjects() API のパラメータとして指定しない限り、この API の挙動に影響を与えることはない。)

    SysInternals では GUI ベースの "ProcessExplorer" 以外にも、コンソール ベースの "Hanle" というツールも提供しています。
    -------------------------------------------------
    Handle
    https://technet.microsoft.com/ja-jp/sysinternals/handle.aspx
    -------------------------------------------------
    "Handle" ツールでは、任意のタイミングでのスナップ ショットを採取することが可能ですので、イベント ハンドルが本当に増殖しているのか、きちんと確認されることをお勧めします。
    (もっとも「名前なしイベント」は、どのプロセスでも結構大量に生成されているので、それ自体が問題になるとは、個人的には思いませんが。。。)
    • 回答としてマーク yanazaki 2017年3月12日 23:32
    2017年3月10日 8:43
  • お馬鹿 様

    質問者のyanazakiです。ご返信をありがとうございます。

    まず、ご教授いただきましたツールで観察します。

    当方のプログラムソースでは、ハンドルの解放は行われているにもかかわらず、

    API コールのその先で獲得したものを解放してくれない。。という事象が常々あります。

    不要となったハンドルのみを掃除してくれる手段等あればよいのですが、

    サーバ再起動などの運用回避で対応している実情です。

    重ね重ねありがとうございます。

    2017年3月12日 23:37
  • 「当方のプログラムソースでは、ハンドルの解放は行われているにもかかわらず」というのは、きちんとライブ デバッグあるいはダンプ ファイルの解析で確認されたことなのでしょうか?
    (「机上デバッグ」での見落としは常に有りうることで、一番大切なのは、「事実」として起きていいることをきちんと把握することだと思います。)

    あなたのプログラム ソースに不備があるから、ハンドル リークが起きているのでは?
    (本当にハンドル リークが起きているのかは、この質問の文面ではわかりませんが。。。)
    もしそのハンドル リークが kernel32.dll 等のマイクロソフト社が提供するシステム コンポーネント側の問題と仮定した場合、それは全ての Windows アプリケーションで起きる可能性がある、起きてもおかしくない。。。ということになりますよね?

    「サーバ再起動などの運用回避で対応」しているのであれば、そのタイミングで一度「完全メモリ ダンプ」を採取して解析してみては?
    自分でダンプ解析できないのであれば、マイクロソフトにお願いすれば、「有償」で解析してくれると思います。(ここでまた「ダンプ解析云々」というと、またアカウント削除されてしまうかもしれないので、これ以上は言及しませんけど。)

    個人的には。。。
    そのサーバー環境に "WinDBG" をインストールさせてもらって、問題アプリのプロセスに WinDBG からアタッチし、"!htrace" コマンドでどのスレッドがなんのハンドルをオープンしているのか、その差異をきちんとチェックすれば、原因を特定できるのは。。。と思っています。
    --------------------------------------------------
    !htrace
    https://msdn.microsoft.com/en-us/library/windows/hardware/ff563208%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
    --------------------------------------------------

    2017年3月13日 2:54