2009-08-12 9 views
0

Hey, je fais des choses client/serveur dans un service Windows. Assez nouveau pour ce genre de choses.CAsyncSocket :: Close Crashes

Le problème que je rencontre est que lorsque j'essaie d'arrêter le service via Service Manager, il se bloque. J'ai ajouté du code MessageBoxes, pour tracer où ils se plantent et j'ai trouvé que quand il ferme le socket d'écouteur il se bloque !!!

J'ai essayé d'exécuter le service en tant qu'application de console, et par moi-même appelé la fonction qui est appelée SERVICE__CONTROL__STOP événement est reçu afin que je puisse reproduire le bogue et déboguer facilement. Mais ça fonctionne bien. Le service Windows ne se bloque quand je l'arrête par Service Manager

Voici un code

La fonction principale

int main(int argc, char* argv[]) 
{ 
// Create the service object 
    CTestService CustomServiceObject; 

    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) 
    { 
     std::cerr << "MFC failed to initialize!" << std::endl; 
     return 1; 
    } 

    // Parse for standard arguments (install, uninstall, version etc.) 
    if (! CustomServiceObject.ParseStandardArgs(argc, argv)) 
    { 
     // StartService() calls ::StartServiceCtrlDispatcher() 
    // with the ServiceMain func and stuff 
     CustomServiceObject.StartService(); 
    } 

    // When we get here, the service has been stopped 
    return CustomServiceObject.m_Status.dwWin32ExitCode; 
} 

La fonction de rappel Gestionnaire de service

// static member function (callback) to handle commands from the 
// service control manager 
void CNTService::Handler(DWORD dwOpcode) 
{ 
    // Get a pointer to the object 
    CNTService* pService = m_pThis; 

    pService->DebugMsg("CNTService::Handler(%lu)", dwOpcode); 
    switch (dwOpcode) { 
    case SERVICE_CONTROL_STOP: // 1 
     pService->SetStatus(SERVICE_STOP_PENDING); 
     pService->OnStop(); 

    // .. 
    // .. 
    // other event handling 
    // .. 
    // .. 
} 

la fonction OnStop()

void CTestService::OnStop() 
{ 
    m_sListener.ShutDown(2); 
    m_sConnected.ShutDown(2); 

    MessageBox(NULL, "After Shutdown", NULL, IDOK); 

    m_sConnected.Close(); 

    MessageBox(NULL, "Closed connected socket", NULL, IDOK); 

    // crashes here when I try to stop through service manager 
    // but if I run as console application works fine and terminates successfully 
    m_sListener.Close(); 

    MessageBox(NULL, "Closed listener socket", NULL, IDOK); 

    ::PostThreadMessage(m_dwThreadID, WM_QUIT, NULL, NULL); 

    MessageBox(NULL, "After PostThreadMessage", NULL, IDOK); 
} 

EDIT: Si une connexion est établie (client se connecte au serveur) et le client ferme la connexion et le service est arrêté ne tombe en panne. Il se bloque uniquement si le socket écoute et aucune connexion n'est acceptée ou le client ne ferme pas la connexion et le service est arrêté :)

Je suppose que c'est clair!

+0

Crash reproduit en version release ou debug? – zabulus

Répondre

-1

Le problème est que vous utilisez très probablement le socket de plusieurs threads. Plusieurs threads et CAsyncSocket ne se mélangent pas - en fait, comme indiqué par la documentation.

Habituellement, vous enfoncez le socket dans son propre thread de travail, puis vous le signalez pour qu'il se ferme lorsque vous en avez besoin.

+0

Mon service est à un seul thread. Je ne sais pas si MFC en interne ou un service Windows crée en interne un autre thread pour son fonctionnement – akif

+0

Un moyen facile de vérifier à coup sûr serait d'utiliser GetCurrentThreadId(). Connectez-vous simplement au résultat où le socket est créé/initialisé et à nouveau là où le socket est fermé (votre routine OnStop). Ensuite, exécutez votre service et voyez ce que sont les résultats. Si les valeurs sont différentes, il y a plus d'un thread touchant ce code. – TheUndeadFish

+0

Ok, juste essayé, mais pas les identifiants de threads étaient les mêmes, donc il n'y a qu'un seul thread en action. – akif

1

Essayez d'ajouter: -

WSADATA data; 
if(!AfxSocketInit(&data)) 
    AfxMessageBox("Failed to Initialize Sockets",MB_OK| MB_ICONSTOP); 

à votre fil ou de classe initialiseur.

Questions connexes