boost::asio::deadline_timer blockt



  • Abend,

    Hab mich gerade erst in boost eingearbeitet und als Übung einfach mal das hier versucht:

    boost::asio::io_service io;
    boost::asio::deadline_timer observeTimer(io, boost::posix_time::seconds(5)); //hier blockt es
    observeTimer.async_wait(handler);
    

    Weiß eventuell wer warum?



  • Btw. das scheint auch der Fall zu sein wenn ich einfach nur den Konstruktor mit nem io_service als parameter calle.

    boost::asio::io_service io;
    boost::asio::deadline_timer observeTimer(io); //block again
    


  • Naja ich würde mal behaupten dass irgend ein Thread io_service::run ausführen muss damit bei ASIO irgendwas geht.



  • hustbaer schrieb:

    Naja ich würde mal behaupten dass irgend ein Thread io_service::run ausführen muss damit bei ASIO irgendwas geht.

    Ja das ist mir schon bewusst 😃
    Aber das run würde doch garnicht ausgeführt werden, da der Konstruktor von deadline_timer ja irgendwie hängt 😕



  • Ich meinte ja auch dass der Ctor von deadline_timer vermutlich deswegen hängen wird, weil zu diesem Zeitpunkt nicht bereits einer run() macht.

    Ich kann dir jetzt keine Stelle in der Doku nennen wo steht dass man run() machen muss bevor man anfangen kann das io_service für bestimmte Dinge zu verwenden. Bin mir trotzdem ziemlich sicher dass das der Grund sein wird.

    Also NICHT

    io_service io;
        deadline_timer timmy_timer(io);
        io.run();
    

    SONDERN

    io_service io;
        thread worker(bind(&io_service::run, &io)); // erstmal laufen lassen
        deadline_timer timmy_timer(io);             // und DANN den timer bauen
    
        // ...
    
        io.stop();
        worker.join();
    


  • Es sollte eigentlich kein Problem sein, eine async. Operation zu queuen (=async_xxx() aufzurufen) bevor io_service::run() aufgerufen wird. Die Queue wird aber erst dann abgearbeitet, wenn run() aufgerufen wird.

    Edit:
    Gerade noch mit VS2012 und Boost 1.53.0 folgenden Code getestet:

    #define _WIN32_WINNT 0x0501
    
    #include <boost/asio.hpp>
    
    void handler(const boost::system::error_code&)
    {
    }
    
    int main()
    {
        boost::asio::io_service io; 
        boost::asio::deadline_timer observeTimer(io, boost::posix_time::seconds(5)); //hier blockt es 
        observeTimer.async_wait(handler);
    }
    

    Bei mir läuft es erwartungsgemäss durch.

    Edit2:
    @BoostAsio: Kannst du mit dem Debugger (oder durch umstellen des Codes) herausfinden ob es im Ctor des Timers blockiert oder in boost::posix_time::seconds(5) ?

    Edit3:
    Hinzu kommt noch die Frage nach der Plattform - die Implementation variiert mit der unterliegenden Technologie. Also, welche Plattform?



  • Da der von dir gezeigte Ausschnitt korrekt ist, muss der Fehler woanders liegen. Versuche mal, dein Programm auf das Wesentliche zu reduzieren und poste das hier.



  • @TyRoXx
    Naja, er könnte immer noch in der ASIO liegen.
    Ist ja nicht so als ob das Ding so perfekt bugfrei wäre...

    Ich würd's einfach mal probieren vorher nen Worker auf run() loszulassen. Falls es dann nämlich läuft, und auch ohne laufen sollte (wo ich mir immer noch nicht so sicher bin), dann könnte man gleich ein Ticket dafür aufmachen.



  • Leider scheint nichts von euren Vorschlägen zu funktionieren, auch das mit dem worker nicht.

    Mein Source sieht momentan so aus (Windows 7):

    void handler(const boost::system::error_code &error)
    {
    	MessageBoxA(0, "Ich auch nicht :<", "", 0);
    }
    
    BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
    {
    
    	if(dwReason == DLL_PROCESS_ATTACH)
    	{
    		boost::asio::io_service io;
    		boost::asio::deadline_timer observeTimer(io, boost::posix_time::seconds(5)); //hier blockt es
    
    		MessageBoxA(0, "Ich werde leider nicht ausgeführt :<", "", 0);
    		observeTimer.async_wait(handler);
    
    		io.run();
    	}
    
    	return true;
    }
    


  • in der DllMain bist du fürchterlich eingeschränkt mit dem was du ausführen darfst. große deadlock-gefahr. das solltest du besser lassen.



  • D.h in 'ner DLL kann ich das mit den deadline_timer vergessen?
    Alles andere von boost::asio funktioniert ja einwandfrei in 'ner DLL (Networking)



  • in ner dll generell schon, nur nicht in der main methode der dll. mach am besten eine separate init-funktion die der dll-nutzer aufrufen muss



  • @BoostAsio
    Man kann aus der DllMain zwar Threads rausstarten, aber die können nicht loslaufen während DllMain noch ausgeführt wird. Weil das Loslaufen bedeuten würde dass erstmal DllMain mit "thread attach" aufgerufen würde. Windows garantiert allerdings dass immer nur ein DllMain -Aufruf gleichzeitig im selben Prozess läuft => der Thread darf erst loslaufen wenn der "DLL-lade-DllMain-Aufruf" returned hat.

    Google mal "Windows loader lock".

    Konstruktoren von globalen/statischen Variablen laufen auch aus der DllMain raus, d.h. das ist auch kein Ausweg.

    => Initialisiere mit call_once oder eben wie anti-dllmain vorgeschlagen hat ne Init-Funktion die der User aufrufen muss.
    (Wobei ich Init-Funktionen gar nicht mag, ich sehe nicht ein wieso eine DLL sich nicht selbst per call_once o.ä. hochziehen kann.)


Log in to reply