[Gelöst] Abnormal program termination nach gescheitertem boost::asio::connect



  • Hallo zusammen,

    ich habe hier ein merkwürdiges Problem. Ich benutze boost::asio, um synchron TCP/IP zu machen. Ich habe bisher ein minimales Spielprojekt, das funktioniert, solange der boost::asio::connect Aufruf gelingt. Tut er das nicht fange ich die Exception, aber nach Verlassen der main() Funktion erhalte ich eine "Abnormal program termination" Fehlermeldung. Ich möchte absichtlich den Fall testen, in dem der Verbindungsaufbau nicht gelingt.

    Ich benutze boost 1.55 unter Windows.
    Hier der relevante Quelltext:

    #include <stream>
    #include <iostream>
    #include <boost/asio.hpp>
    
    template<typename Predicate>
    boost::asio::ip::tcp::resolver::iterator resolve_ip_address( boost::asio::io_service& service,
                                                                 std::string const& host,
                                                                 unsigned short port,
                                                                 Predicate predicate )
    {
       boost::asio::ip::tcp::resolver resolver( service );
       boost::asio::ip::tcp::resolver::query query( host, std::to_string( port ) );
    
       boost::asio::ip::tcp::resolver::iterator const end;
       for( boost::asio::ip::tcp::resolver::iterator it = resolver.resolve( query ); it != end; ++it )
       {
          boost::asio::ip::address const& addr = it->endpoint().address();
          if( predicate( addr ) )
          {
             return it;
          }
       }
       return end;
    }
    
    boost::asio::ip::tcp::resolver::iterator resolve_ip_address_v4( boost::asio::io_service& service,
                                                                    std::string const& host,
                                                                    unsigned short port )
    {
       auto predicate = []( boost::asio::ip::address const& addr )
       {
          return addr.is_v4();
       };
       return resolve_ip_address( service, host, port, predicate );
    }
    
    boost::asio::ip::tcp::resolver::iterator resolve_ip_address_v6( boost::asio::io_service& service,
                                                                    std::string const& host,
                                                                    unsigned short port )
    {
       auto predicate = []( boost::asio::ip::address const& addr )
       {
          return addr.is_v6();
       };
       return resolve_ip_address( service, host, port, predicate );
    }
    
    
    class TestClient
    {
       boost::asio::io_service      Service_;
       boost::asio::ip::tcp::socket Socket_;
       std::string                  Host_ = "localhost";
       unsigned short               Port_ = 12000;
       unsigned int                 Timeout_ = 5000;
    
       TestClient::TestClient() :
          Socket_( Service_ )
       {
       }
    
       TestClient::~TestClient()
       {
          disconnect();
       }
    
       bool connect()
       {
          boost::asio::ip::tcp::resolver::iterator beg = resolve_ip_address_v6( Service_, Host_ , Port_  );
          boost::asio::ip::tcp::resolver::iterator const end;
          if( beg == end )
          {
             beg = resolve_ip_address_v4( Service_, Host_ , Port_  );
             if( beg == end )
             {
                return false;
             }
          }
          // Option 1: Exception bei Fehlschlag
          boost::asio::connect( Socket_, beg );
    
          // Option 2: ErrorCode auswerten
          // boost::asio::error_code ec;
          // boost::asio::connect( Socket_, beg, ec );
          // if( ec ) ....
          
          int socket_timeout = static_cast<int>( Timeout_  );
          Socket_.set_option( boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO>{ socket_timeout } );
          Socket_.set_option( boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_SNDTIMEO>{ socket_timeout } );
          return true;
       }
    };
    
    int main()
    {
       TestClient client;
       try
       {
          client.connect();
       }
       catch( boost::system::system_error const& excp )
       {
          std::err  << "Fehler beim Verbindungsaufbau\n";
       }
       return 0;
    }
    

    Ich kann das Verhalten direkt auf boost::asio::connect in Zeile 80 bzw. 84 zurückführen, sobald ich die Zeile auskommentiere beendet sich das Programm normal. Hat da jemand eine Idee?



  • Steht vor "Abnormal program termination" noch ein Text bzgl. "Terminate"?
    Ich habe dazu Can't catch Boost.Asio exceptions inside coroutines gefunden (s. Beiträge weiter unten), also anscheinend ein Fehler beim Exception-Handling (unter Windows).



  • @DocShoe sagte in Abnormal program termination nach gescheitertem boost::asio::connect:

    Ich benutze boost 1.55 unter Windows.

    Ist ja schon etwas abgehangen ...

    @DocShoe sagte in Abnormal program termination nach gescheitertem boost::asio::connect:

    Tut er das nicht fange ich die Exception, aber nach Verlassen der main() Funktion erhalte ich eine "Abnormal program termination" Fehlermeldung.

    Was macht denn disconnect()?



  • Oh, hier der Nachtrag:

    void TestClient::disconnect()
    {
       if( connected() )
       {
          Socket_.shutdown( boost::asio::ip::tcp::socket::shutdown_both );
          Socket_.close();
       }
    }
    
    bool TestClient::connected() const
    {
       return Socket_.is_open();
    }
    

    Ja, ich weiß, 1.55 ist nicht aktuell. Wurde mit unserer, ähm, ich nenn´s vorsicht Compiler Suite, mitgeliefert. Ich könnte versuchen, eine neuere Version zu bauen, aber das ist immer ein Problem und mit viiiel Arbeit verbunden. Hab da schon einige böse Überraschungen erlebt, wo der Code zwar compiliert aber abstürzt oder nicht das tut, was er soll. Deswegen bleibe ich lieber bei dem, was der Hersteller mitliefert und (wieder ähem) getestet hat.



  • Ich glaube, ich hab´s gefunden....
    boost::asio::ip::tcp::socket::is_open() liefert true zurück, selbst wenn der Verbindungsaufbau gescheitert ist o.O Wer denkt sich sowas aus? Jedenfalls wird im Destruktor vom TestClient shutdown und close auf dem Socket aufgerufen, obwohl er nicht verbunden ist, und dabei wird system_error geworfen. Da das nach dem Verlassen der main() funktion passiert wird die Exception nicht gefangen und führt zur "Abnormal program termination". Ich verpacke den Socket jetzt in einen unique_ptr und merke mir den erst dann, wenn die Verbindung aufgebaut werden konnte.

    Danke für eure Hilfe. der Hinweis "Was macht disconnect()?" hat mich auf die richtige Spur gebracht.

    Off-topic:
    Ist boost:asio ein Wesenstest für Hartnäckigkeit, Frusttoleranz und der Bereitwilligkeit, endlos viel Zeit mit mieser Doku zu verbringen?



  • @DocShoe sagte in Abnormal program termination nach gescheitertem boost::asio::connect:

    Off-topic:
    Ist boost:asio ein Wesenstest für Hartnäckigkeit, Frusttoleranz und der Bereitwilligkeit, endlos viel Zeit mit mieser Doku zu verbringen?

    Spricht jedenfalls einiges dafür.

    Immerhin gibt's ja viele Beispiele.



  • @DocShoe sagte in [Gelöst] Abnormal program termination nach gescheitertem boost::asio::connect:

    Off-topic:
    Ist boost:asio ein Wesenstest für Hartnäckigkeit, Frusttoleranz und der Bereitwilligkeit, endlos viel Zeit mit mieser Doku zu verbringen?

    Es gibt schlimmeres. Gnome libsecret wäre so ein Beispiel.



  • @DocShoe sagte in [Gelöst] Abnormal program termination nach gescheitertem boost::asio::connect:

    Off-topic:
    Ist boost:asio ein Wesenstest für Hartnäckigkeit, Frusttoleranz und der Bereitwilligkeit, endlos viel Zeit mit mieser Doku zu verbringen?

    Kann ich so unterschreiben. Mit neueren boost::asio versionen wird es nur noch schlimmer mit dem ganzen executor Kack, der da nun auch drin ist… Und so gut wie Null Doku dazu.


Log in to reply