[ back to toc ]

WinNT service hang on shutdown

Date: 2002/02/18 17:55

Q:
Hi Peter:

This is a follow up to a question a few days before. I'm developing with
Visual C++ on Windows NT. I am trying to write a service in which the
main thread spawns off a listen thread, and in turn spawns off a client
thread to do the work. Using semaphores, I limit the client threads
available.

My problem was that NT hangs on shutdown. However, I could manually stop
the service and then if I shutdown, I would be okay.

Your suggestion was that I should call TerminateThread. Before I do
something that drastic, I also read another interesting thing you
mentioned... "If you start an ISAPI application that gets into an
infinite loop, you will not be able to stop the service."

That got me to thinking about my ListenThread function which loops until
it receives a SetEvent signal from the StopService function. If you don't
mind, I'd like to run over some of my functions with you.

void StartServ(void){

//initiate socket, bind, listen, etc.

ghExit = CreateEvent(NULL, TRUE, FALSE, NULL);
ghListenExit = CreateEvent(NULL, TRUE, FALSE, NULL);
gdwListenThread = _beginthreadex(NULL, 0, ListenThread, &ghExit, 0,
&ThreadAddr);

}

void StopService(void){

//error checking snipped

closesocket(listenSocket);
SetEvent(ghExit);
SetEvent(ghListenExit);
WaitForSingleObject((HANDLE gdwListenThread, INFINITE);
CloseHandle((HANDLE)gdwListenThread);
CloseHandle(ghExit);
CloseHandle(ghListenExit);
WSACleanup();
}

unsigned __stdcall ListenThread(void *pVoid)
{
HANDLE hSem;
SOCKET theClient;
unsigned ThreadAddr;
DWORD dwClientThread;
LPREQUEST lpReq;
int nLen;
DWORD dwRet;
HANDLE hNoClients;
LPHANDLE pHandle = (LPHANDLE)pVoid;
bool temp;

//error checking snipped

hSem = CreateSemaphore(NULL, 2, 2, "ClientSemaphore");

hNoClients = InitClientCount();

temp = 0;

while(!temp){

dwRet = WaitForSingleObject(ghListenExit, 0);

switch (dwRet){

case WAIT_OBJECT_0:
temp = 1;
break;

default:
nLen = sizeof(SOCKADDR_IN);

theClient = accept(listenSocket, NULL, &nLen);

lpReq = (REQUEST*)malloc(sizeof(REQUEST));

lpReq->Socket = theClient;

dwClientThread = _beginthreadex(NULL, 0, ClientThread, lpReq, 0,
&ThreadAddr);

CloseHandle((HANDLE)dwClientThread);

break;

}

}

dwRet = WaitForSingleObject(hNoClients, 5000);

DeleteClientCount();

return (1);

}

I think that most likely, my problem lies with my ListenThread function.
I wasn't quite sure how to break out of that infinite loop. Do you see
anything wrong?

I hope the code snippets are understandable. I'm just starting with IPCs
and I tried to trim as much code I could to just get the point across.

Thanks for any help.

A:
You should in some way notify all the threads to call TerminateThread for
themselves! Not from another thread. That would be too drastic.

For example you should set a semaphore, or alter a variable that the
different threads should check from time to time whenever it is
appropriate to terminate their functioning. You should not call
TerminateThread to kill another thread if possible because a thread may be
in the middle of some sensitive operation like writing to a file.

If a thread is looping around, as it is usually and in the loop it waits
for some client access infinitely, then your StopService code should mimic
a client attaching to the thread. Whent he client appears the worker
thread should check if the system is shutting down and then do not service
the actual client but stop.

Regards,
Peter

[ back to toc ]