[Win32]プログラム異常終了後Listenゾンビプロセス(?)になる
Posted: 2012年9月28日(金) 15:28
お世話になっております。
趣味で簡易HTTPサーバプログラムを作っていますが、プログラムが異常終了した後
ゾンビのように生き残ってしまう現象を回避・改善したく質問させて頂きます。
環境:WinXP Home SP3、VC2008Express、C言語+Win32API
・プログラムはウィンドウを1つ持ち、
・winsock2で接続を待ち受けるTCPサーバプログラムです。
・bind、listen後、NULLポインタアクセス違反が発生すると、プロセスは強制終了させられますが、
・なぜかlistenしたポートが解放されず、netstat -a で見ると「LISTENING」のままになっています。
・そのためか、ふたたびプログラムを起動しても、bindエラーが発生してしまいます。
・しばらく放置しても回復しません。
・タスクマネージャのプロセス一覧には、問題のプロセスは存在しません。
・netstat -ao で問題のプロセスIDは表示確認できます。
・そのプロセスIDを、OpenProcess/TerminateProcess すると、エラー ERROR_ACCESS_DENIED(5) になります。
このような、ゾンビみたいなプロセスをきれいに葬り、ポートを解放する方法はないでしょうか?
できればOS再起動せずに回復させたいです。
以下は、私の環境で問題が発生する小プログラムです。
趣味で簡易HTTPサーバプログラムを作っていますが、プログラムが異常終了した後
ゾンビのように生き残ってしまう現象を回避・改善したく質問させて頂きます。
環境:WinXP Home SP3、VC2008Express、C言語+Win32API
・プログラムはウィンドウを1つ持ち、
・winsock2で接続を待ち受けるTCPサーバプログラムです。
・bind、listen後、NULLポインタアクセス違反が発生すると、プロセスは強制終了させられますが、
・なぜかlistenしたポートが解放されず、netstat -a で見ると「LISTENING」のままになっています。
・そのためか、ふたたびプログラムを起動しても、bindエラーが発生してしまいます。
・しばらく放置しても回復しません。
・タスクマネージャのプロセス一覧には、問題のプロセスは存在しません。
・netstat -ao で問題のプロセスIDは表示確認できます。
・そのプロセスIDを、OpenProcess/TerminateProcess すると、エラー ERROR_ACCESS_DENIED(5) になります。
このような、ゾンビみたいなプロセスをきれいに葬り、ポートを解放する方法はないでしょうか?
できればOS再起動せずに回復させたいです。
以下は、私の環境で問題が発生する小プログラムです。
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
LRESULT CALLBACK WindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
{
switch( msg ){
case WM_CREATE:
{
SOCKET sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( 54326 );
addr.sin_addr.s_addr = INADDR_ANY;
if( bind( sock, (SOCKADDR*)&addr, sizeof(SOCKADDR) )==SOCKET_ERROR ){
MessageBox(hwnd,"bindエラー終了します","エラー",MB_ICONERROR);
return -1;
}
listen( sock, 5 );
SetWindowText( hwnd, "listenしました" );
}
CreateWindow(
"button", "ぬるぽゾンビ化", WS_CHILD |WS_VISIBLE
,20,20,200,30, hwnd, (HMENU)1, GetModuleHandle(NULL),NULL
);
break;
case WM_COMMAND:
if( LOWORD(wp)==1 ) strlen( NULL );
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hwnd, msg, wp, lp );
}
int WINAPI WinMain( HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow )
{
WSADATA wsaData;
WNDCLASS wc;
MSG msg;
WSAStartup( MAKEWORD(2,2), &wsaData );
memset( &wc, 0, sizeof(wc) );
wc.lpfnWndProc = WindowProc;
wc.hInstance = hinst;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wc.lpszClassName = "MainForm";
RegisterClass(&wc);
CreateWindow(
"MainForm", "ゾンビ"
,WS_OVERLAPPEDWINDOW |WS_VISIBLE
,CW_USEDEFAULT, CW_USEDEFAULT, 300, 100
,NULL,NULL, hinst,NULL
);
while( GetMessage( &msg, NULL, 0, 0 ) >0 ){
TranslateMessage( &msg );
DispatchMessage( &msg );
}
WSACleanup();
return (int)msg.wParam;
}