BOOST Thread ist join in bestimmten Situationen obsolet?



  • Hi Liebe Community,

    ich bin heute auf ein Verhalten gestoßen im Zuge von Boost thread, dass mir ein wenig Kopfschmerzen bereitet. Folgender Code:

    void foo(){
         try{   
             while(true){
                int a = read(); // blockiert bis ein Wert vorliegt oder eine Exception geworfen wird
               ...
             }
         }
         catch(...){
         }
    }
    
    class Foo{
         public:
                    Foo(){
                           ptr = std::make_shared<boost::thread>(foo);
                    }
        private:
                  std::shared_ptr<boost::thread> ptr;
    }
    
    int main(){
          Foo f;
         
           //irgendwann später
           read.stop(); // jetzt wird in foo eine exception gefangen;
          return 0;
    }
    

    Mein Problem ist, das Programm blockiert nicht, hat keinen Zugriffsfehler oder sonst wie ein komisches Verhalten. Es verhält sich so als hätte ich ordentlich mit einem join darauf gewartet. Ist dies so gewollt oder habe ich nach ca. 71 Versuchen mit verschiedenen Timing verhalten einfach nur Glück gehabt.
    Ich benutzte aktuell die Boost Version 1.67

    Grüße



  • Das war früher so, und ist vermutlich immer noch Default.

    https://www.boost.org/doc/libs/1_67_0/doc/html/thread/thread_management.html#thread.thread_management.thread.destructor

    • if defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls detach(), DEPRECATED

    • if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE: If the thread is joinable calls to std::terminate. Destroys *this.



  • Dann ist das join in gewissen Situationen nicht nötig? Das heißt ich kann dies so stehen lassen wie oben, solange ich sicher bin das ich den Thread aufwecke und nicht in der Endlosschleife feststecke?

    Ich weiß, ich sollte das mit einem join auf jeden fall noch mit dem Parent in Synchronisation bringen. Allerdings habe ich mich gefragt wie kritisch der Bug von mir ist...
    Wenn ich das jetzt richtig verstehe nicht so sehr, ist das korrekt ?



  • Naja...
    Also ich würde dir empfehlen immer manuell zu joinen.

    1. In der C++11 Variante std::thread ist es immer ein Fehler nicht zu joinen.
    2. Je nachdem wie Boost konfiguriert ist es es dort ebenso ein Fehler.
    3. Implizites Joinen ist einfach gefährlich, was ja auch der Grund ist warum die C++11 Variante es nicht macht und vom Benutzer verlangt explizit zu joinen. Steht ja auch so in der von mir verlinkten Doku zum boost::thread Destruktor:

    The reason to moving to std::terminate is that either implicitly detaching or joining a joinable() thread in its destructor could result in difficult to debug correctness (for detach) or performance (for join) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. Join the thread before destroying or use a scoped thread.

    Wobei das nicht so ganz vollständig ist: Auch implizites Joinen kann zu "correctness" Bugs führen. Nämlich dann wenn man sich damit einen Deadlock einfängt weil der Benutzer einfach macht und nicht nachdenkt was alles passieren könnte (welche Wege die Ausführung seines Programms nehmen könnte).

    ps: Wieso shared_ptr<thread> und nicht z.B. scoped_ptr? Willst du dein Objekt etwa kopierbar halten? Pfui-Spinne. Ein Objekt das einen Thread besitzt sollte niemans kopierbar sein!



  • Ja, ich sage auch das es ein Bug ist. Allerdings muss ich dann nicht direkt morgen ein neues Release meiner Software durchführen sondern kann mir ein paar Tage zeit nehmen. Da es sich nicht um ein super kritischen Bug handelt, der die Produktion gefährdet. Sondern um einen Bug, den ich im nächsten Release entfernen kann.

    scoped_ptr sagt mir ehrlich gesagt nichts.



  • @pmqtt OK, wenn du das so meinst, dann ja (=dann ist es OK).

    scoped_ptr sagt mir ehrlich gesagt nichts.

    Das ist einfach ein Smart-Pointer der "unique ownership" hat. Also der ist nicht kopierbar oder sowas, löscht aber auch wie shared_ptr selbständig das Objekt das er kontrolliert.

    ps: Wenn du möchtest das Leute auf deren Beiträge du antwortest deine Antwort auch sehen, dann wäre es vorteilhaft wenn du sie entweder mit @Benutzername erwähnst, oder den "Antworten" Link unter des jeweiligen Beitrags verwendest.
    Dann bekommen die nämlich das nächste mal wenn sie das Forum aufmachen eine Benachrichtigung. So wie du es machst, also einfach einen weiteren Beitrag drunterschreiben, bekommen sie keine.


Log in to reply