Rework port listening timeout 13/185913/3
authorIgor Kotrasinski <i.kotrasinsk@partner.samsung.com>
Thu, 2 Aug 2018 10:25:26 +0000 (12:25 +0200)
committerIgor Kotrasinski <i.kotrasinsk@partner.samsung.com>
Tue, 21 Aug 2018 10:37:29 +0000 (12:37 +0200)
Apparently passing in lambda with automatic storage duration to boost::spawn
causes UB. Use a static method instead and make sure to cancel it properly
after we're done listening.

Change-Id: Ia3817a82fba6150690879d6839b8466e4072a3bb
Signed-off-by: Igor Kotrasinski <i.kotrasinsk@partner.samsung.com>
simulatordaemon/debugproxy/inc/ProxySession.h
simulatordaemon/debugproxy/src/ProxySession.cpp

index efe6c90..3799c71 100644 (file)
@@ -19,6 +19,11 @@ private:
        boost::asio::io_service &io();
        uint32_t read_forwarded_port(yield_ctx yield);
        void setup_port_socket(int port, yield_ctx yield);
+       /* This might be scheduled after ProxySession is destroyed, so let's keep it static */
+       static void stop_port_listening_at_timeout(
+               std::shared_ptr<boost::asio::deadline_timer> timeout,
+               std::shared_ptr<ip::tcp::acceptor> port_acceptor,
+               yield_ctx yield);
        std::shared_ptr<AsyncEvent> start_forwarding();
        template<typename T>
        void close_socket(std::shared_ptr<boost::asio::basic_stream_socket<T>> sock);
index 1067f70..8d3f19c 100644 (file)
@@ -36,29 +36,40 @@ uint32_t ProxySession::read_forwarded_port(yield_ctx yield)
        return target_port[0];
 }
 
+void ProxySession::stop_port_listening_at_timeout(
+       std::shared_ptr<boost::asio::deadline_timer> timeout,
+       std::shared_ptr<ip::tcp::acceptor> port_acceptor,
+       yield_ctx yield)
+{
+       timeout->expires_from_now(ProxySession::PORT_TIMEOUT);
+       try {
+               timeout->async_wait(yield);
+       } catch (boost::system::system_error &e) {
+               /* We were canceled, just continue */
+       };
+       port_acceptor->cancel();
+}
+
 void ProxySession::setup_port_socket(int port, yield_ctx yield)
 {
        ip::tcp::endpoint port_ep(ip::address::from_string("127.0.0.1"), port);
        auto port_acceptor = std::make_shared<ip::tcp::acceptor>(this->io(), port_ep);
-
        /* FIXME: We don't want to read data from local socket before
         * forwarding it, so checking if it closed while we're listening on the
         * port is difficult. Let's just timeout instead.
         */
-       auto stop_at_timeout =
-               [this, &io = this->io(), acceptor_ptr = std::weak_ptr<ip::tcp::acceptor>(port_acceptor)]
-               (yield_ctx yield) {
-                       boost::asio::deadline_timer timeout(this->io());
-                       timeout.expires_from_now(ProxySession::PORT_TIMEOUT);
-                       timeout.async_wait(yield);
-                       auto acceptor = acceptor_ptr.lock();
-                       if (!acceptor)
-                               return;
-                       acceptor->cancel();
+       auto timeout = std::make_shared<boost::asio::deadline_timer>(this->io());
+       boost::asio::spawn(this->io(), boost::bind(
+               &ProxySession::stop_port_listening_at_timeout,
+               timeout, port_acceptor, _1));
+       try {
+               port_acceptor->async_accept(*this->port_socket, yield);
+       } catch (boost::system::system_error &e) {
+               if (e.code() == boost::asio::error::operation_aborted)
                        LOGI(MODULE_DEBUGPROXY, "(%p) Timed out waiting for a port connection", this);
-       };
-       boost::asio::spawn(this->io(), stop_at_timeout);
-       port_acceptor->async_accept(*this->port_socket, yield);
+               throw;
+       }
+       timeout->cancel();
 }
 
 std::shared_ptr<AsyncEvent> ProxySession::start_forwarding()