過去の投稿記事 new!
・【画像】漫画でわかる外国人参政権
・東京電力のHPで停電状態が確認できたり(サービス再開!)
・戦国時代 ~ 江戸時代の徳川家康が熱かった
・vaio のバッテリは寿命が短いような気がする
・話題の Western Digital 製 WD20EARS を購入した
・C01LC をビックカメラで買ってきた
・2025年には空中都市が現実化?!
・【動画】わかりやすい「宇宙ひも理論」
・今世紀には「富士山噴火」「東海連動地震」「首都圏直下型地震」か?
・滅びた町、南浜町が Googleストリートビューで見れる

【 amazon 送料無料キャンペーン 】

バックリンクはご自由にどうぞ!     http://mfsocket.blogspot.com/feeds/posts/default?alt=rss リンク集 / ログイン

2008/04/23
Winsock でハンドルリーク

 
今、あるフリーソフトでハンドルリークしている事がわかりました( ´д`)
 
と言っても環境によっては、発生しているのかひじょーにわかりづらく、
今日まで発見が遅れたのですが。。
 
 
具体的なことはまた更新すると思いますが、ようは
 
   WSAStartup() /  WSACleanup() 
 
 
を対で何回も呼んで、socket を生成しているとハンドルリークするみたいです。
 
 
今まで自分の設計としては "通信をするときだけ"
 
Winsock の初期化/解放をしていた のですが、
 
それでは問題があったようです( ´д⊂
 
 
今テストしている OS は WindowsXPPro/SP2 で、
 
   VC6.0    SP1 Release版のマルチスレッドDLL
   VC2005 SP1 Release版のマルチスレッドDLL
 
でコンパイル/リンクした exe でダメだったので、たぶん 全 Windows で同じ
結果になると思います。
 
 
ソースのイメージとしては以下のとおり
#include <Winsock2.h>
#include <Windows.h>
#include <process.h>

UINT ConnectThread()
{
      SOCKET s;
      s = socket( ... );
     // TCP でサーバと通信する
 
      closesocket(s);
      _endthreadex(0);
      return 0;
}

UINT ManagerThread()
{
      HANDLE h[4];
      int i, ret;
      while( true ){
            // WinSock の初期化 ここだ!
            WSADATA wsa;
          ret = WSAStartup( MAKEWORD(2,0), &wsa );
 
            // スレッドの生成
            for( i=0 ; i<4 ; i++ ){
                 h[i]  = (HANDLE)_beginthreadex( ConnectThread );
            }
            // スレッドの終了待機          
            for( i=0 ; i<4 ; i++ ){
                 WaitforSingleObject( h[i], INFINITE );
                 CloseHandle( h[i] );
            }

            // WinSock の解放 ここ!
            WSACleanup();

            Sleep( 1000 * 20 );     

     }

     _endthreadex(0);
      return 0;
}

 

int main( int argc, char* argv[] )
{
      HANDLE h = (HANDLE)_beginthreadex( ManagerThread );
      WaitforSingleObject( h, INFINITE );
      CloseHandle( h  );
      return 0;
}

 
簡単に説明するとまず、
 
マネージャスレッドというのが、メインスレッドから生成されます。
 
そしてマネージャスレッドからは、実際にコネクション処理を実行する
コネクションスレッド4つほど生成させます。
 
そのコネクションスレッドの中でソケットのクライアント側をコーディングする
わけです。
 
 
そこでは非常に単純で、socket()  connect()   send()   recv()   shutdown() 
closesocket()  を順にやっていくだけです。
 
蛇足ですが、実際はエラー処理をもっと組み込んでいます。
 
 
そしてそのプログラムを1時間~4時間ほど実行すると、、
落ちます。
 
 
チェックの手順としては、タスクマネージャー等で本プロセスを監視していると、
 
ほんのちょっとずつ・・・ハンドルリークしていってる
 
のがわかります。
 
 
これを回避するには、ソースの中でここ!と書いてる箇所をループの外に出せば
回避可能になります。
 
私の憶測も含まれてますが、
 
   WSAStartup()  は何回コールしても良い → msdn かどっかでもそうあった
 
   WSAStartup() / WSACleanup()  のセットはプロセスで1回のみが良い→結論 

ってな感じですな( ´д`)

0 コメント:

  • コメントには <b>, <strong>, <em>, <i>, <a> など一部の HTML タグを使用できます。