Thread wird sporadisch nicht mehr aufgerufen



  • Hi an alle,

    folgendes, ich habe einen Thread mit einer Endlosschleife. Abgebrochen wird dieser Thread erst beim Beenden des Programms durch setzen eines Events.
    Nun kommt es sporadisch unter XP vor, dass der Thread irgendwann nicht mehr aufgerufen wird.

    Der Thread selbst wird über eine boolsche Variable am Leben gehalten. Diese ist global ebenso wie die Struktur für meine benötigten Thread Parameter. Innerhalb der Schleife wird die ganze Zeit ein Port mit recvfrom abgefragt ob er neue Daten erhalten hat. Hierbei handelt es sich um eine Non Blocking Abfrage.
    Hier mal ein kleiner Ausschnitt:

    DWORD MYClass::MyThread(LPVOID pParam)
    {
        MyStruct *myStruct = (MyStruct*)pParam;
        while(not_done)
        {
            if(recvfrom(myStruct->m_socket, buf, sizeof(buf), 0, (SOCKADDR*)&sa,    
               &salen) !0 -1)
            {
                  EnterCriticalSection(&cs);
                  //.. do Something
                  LeaveCriticalSection(&cs);
            }
        }
    }
    

    Was könnte hier falsch laufen?



  • Deadlock? Hülle mal die gesamte Funktion mit der CS ein.



  • DWORD MYClass::MyThread(LPVOID pParam)
    {
    EnterCriticalSection(&cs);

    MyStruct *myStruct = (MyStruct*)pParam;
    while(not_done)
    {
    if(recvfrom(myStruct->m_socket, buf, sizeof(buf), 0, (SOCKADDR*)&sa,
    &salen) !0 -1)
    {
    //.. do Something
    }
    }
    LeaveCriticalSection(&cs);
    return 0;
    }

    Habe es jetzt mal so umgestellt. Passiert aber dennoch 😕


  • Mod

    Debugger - Break All - Alles Threads ansehen und kontrollieren was sie machen (Callstack ansehen)



  • Einzige was sich feststellen lässt ist, das die CWinThread::Run Methode durchlaufen wird. Aber er springt nicht mehr in meine Thread Methode rein obwohl die not_done Variable auf true bleibt und auf jeden Fall auch Antworten vom Server kommen.

    Zumindest mit meinen wenigen Erfahrungen mit solchen Thread Fehlern finde ich nicht mehr raus.

    Was ich noch rausfinden konnte, sobald ich auf Break All gehe beginnt der Debugger in der Methode AfxInternalPumpMessage aus der thrdcore.cpp in welcher dann der ThreadState über AfxGetThreadState geholt wird. In der zurückgegebenen _AFX_THREAD_STATE Struktur ist m_nLastMsg auf 160 aber m_nCurMsg auf 0. Hat das evtl. eine Bedeutung?



  • Schalt mal auf deinen Thread um und schau nach, wo der steht.



  • Ich finde meinen Thread nicht unter CallStack und auch nicht unter Debug -> Threads. Dort sind zwar einige Win32 Threads aufgeführt. Die kann ich aber nur im Dissassembler aufrufen.


  • Mod

    Wenn Du die Threads im Threadfenster einzeln durchgehst, dann musst Du im jeweiligen Callstack irgendwo Deinen Code sehen.
    In jedem Fall!
    Ansonsten lass Dir die Thread-IDs im Debug Trace ausgeben und lokalisiere sie so.



  • Ok hab es gefunden. Dort steht er an einer WaitForSingleObject welche auf ein Event wartet welches das Beenden eines anderen Threads bekannt gibt.



  • CrazyPlaya schrieb:

    Ok hab es gefunden. Dort steht er an einer WaitForSingleObject welche auf ein Event wartet welches das Beenden eines anderen Threads bekannt gibt.

    Lass mich raten: Dieses WaitForSingleObject steht in "//.. do Something", und der andere Thread benutzt dieselbe Critical Section?



  • Bzw. Es steht in einer Funktion welche innerhalb von Do Something aufgerufen wird. Somit wird es ja von Critical Section miteingeschlossen.



  • Ist dir denn klar, was passiert, wenn du an dieser Stelle auf einen Thread wartest, der nicht weiterlaufen kann, weil er auf diese Critical Section wartet?



  • Ehrlich gesagt nicht wirklich



  • Ein Deadlock. Keiner der beiden Threads kann weiterlaufen, weil er auf den jeweils anderen wartet.



  • Hab ich mir gedacht dass ich hier meinen Deadlock finde. Aber danke für die Unterstützung, da wäre ich alleine wahrscheinlich nicht so schnell hintergekommen. Muss ich nur noch schauen wie ich das löse 😃



  • Jemand einen Tipp für mich? Also innerhalb meines ersten Threads starte ich einen neuen Thread einer anderen Klasse. Um den neuen Thread zu stoppen gibt es eine Methode do_stop(). Diese sendet ein Event welches darauf hinweisen soll, dass der Thread beendet werden soll.

    //Thread der anderen Klasse.
    while(!bStop)
    {
       if(WaitForSingleObject(m_hEventStopThread, 0) == WAIT_OBJECT_0)
       {
          bStop = true;
          break;
       } 
       else
       {
           //Do Something
       }
    }
    SetEvent(m_hEventThreadHasTerminated):
    ExitThread(0);
    

    Nach dem setzen des Stop Events wartet meine Methode auf das Event m_heventThreadhasTerminated und zwar INFINITE. Hier überschneiden sich dann die beiden Threads.
    Was kann man tun, das der erste Thread welcher den neuen Thread aufgerufen hat solange warte bis der neue Thread sich beendet und den Event hasTerminated ausgelöst hat?


  • Mod

    Dein wartender Thread darf halt nichts blockieren was der Thread der terminieren soll benutzen will.

    Warum verwendest Du ExitThread und CreateThread? Bist Du scharf auf Memory-Leaks?
    Ein rteurn ist hier sicherlich angebrachter...

    http://blog.m-ri.de/index.php/2007/11/28/createthread-und-die-crt/



  • und ich such schon die ganze Zeit wie ein verrückter woher die Memory Leaks kommen könnten.

    Warum bleiben denn da soviele Leaks übrig?


  • Mod

    Weil Du evtl. noch anderes nicht freigibst...



  • Und beginthreadex macht dieses?


  • Mod

    Nein beginthreadex sorgt zumindest für ein kontrolliertes Anlegen/Zerstören threadlokalen CRT Daten.
    Wenn Du die MFC verwendest solltest Du AfxBeginThread verwenden.
    http://blog.m-ri.de/index.php/2008/02/28/afxbeginthread-versus-_beginthreadex/


Anmelden zum Antworten