shutdown( ) blocks forever

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

shutdown( ) blocks forever

Boost - Users mailing list

I have a server that accepts ssl connections on port 443. I am using the boost libraries for the server implementation. Below is the code snippet:
    ssl_socket socket_;
{
   // Open the acceptor with the option to reuse the address (i.e.
 SO_REUSEADDR).
     boost::asio::ip::tcp::resolver resolver(io_service_);
     boost::asio::ip::tcp::resolver::query query(address, port);
     boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
     acceptor_.open(endpoint.protocol());
     acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
     acceptor_.bind(endpoint);
     acceptor_.listen(1000);
      start_accept();
}

void server::start_accept() {
        new_connection_.reset(
                        new connection(io_service_, connection_manager_, request_handler_,
                                        context_));
        acceptor_.async_accept(new_connection_->socket(),
                        boost::bind(&server::handle_accept, this,
                                        boost::asio::placeholders::error));
}

void server::handle_accept(const boost::system::error_code& e) {
        // Check whether the server was stopped by a signal before this completion
        // handler had a chance to run.
        if (!acceptor_.is_open()) {
                return;
        } else {
                 start();
        }
         start_accept();
}


void server::start() {
        
        socket_.async_handshake(boost::asio::ssl::stream_base::server,
                        boost::bind(&connection::handle_handshake, this,
                                        boost::asio::placeholders::error));
        if (boost::asio::placeholders::error) {
        //      printf("Error is there. Check it\n");
        }
}

void connection::handle_handshake(const boost::system::error_code& error) {
        
        if (!error) {
                DEBUG("async read some");
                socket_.async_read_some(boost::asio::buffer(buffer_),
                                boost::bind(&connection::handle_read, shared_from_this(),
                                                boost::asio::placeholders::error,
                                                boost::asio::placeholders::bytes_transferred));
        } else {
                std::cout << "Error number: " << error.value();
                std::cout << " Error message: " << error.message();
                std::cout << " Error category: " << error.category().name() << std::endl;
                delete this;
        }
}

When I initiate multiple clients to connect to the server, most of the time the connection succeeds i.e TCP handshake followed by SSL handshake succeeds and I am able to do data transfer. However, there are times when the TCP handshake succeeds (as seen by wireshark) but the SSL request isn't responded to by my server. I am able to see the SSL handshake request coming from the client onto my server, but the server doesn't respond, neither is my handle_accept() function gets called. When I check the output of netstat, I see a lot of data pending in the Recv-Q.

Below is the output of netstat -atn command on the server during one such scenario:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp       15      0 0.0.0.0:443             0.0.0.0:*               LISTEN
tcp        0    213 10.110.112.1:443        10.110.112.2:52363      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52624      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52581      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52646      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52749      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52824      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52805      ESTABLISHED
tcp      180      0 10.110.112.1:443        10.110.112.2:52645      ESTABLISHED
tcp        0    471 10.110.112.1:443        10.110.112.2:52362      ESTABLISHED
tcp        1      0 10.110.112.1:443        10.110.112.3:39129      CLOSE_WAIT
tcp      183      0 10.110.112.1:443        10.110.112.3:39130      CLOSE_WAIT
tcp      180      0 10.110.112.1:443        10.110.112.2:52595      ESTABLISHED
tcp      183      0 10.110.112.1:443        10.110.112.3:39131      CLOSE_WAIT

Upon further debugging, I see that the call to ssl socket member function shutdown() blocks sometimes forever and sometimes for at least 5 - 10 minutes due to which no further data is taken in and the recv-q indicates pending bytes. This is how my write handler is. Any help on where I am going wrong would be greatly appreciated:

void connection::handle_write(const boost::system::error_code& e) {
           if (!e) {
                boost::system::error_code ec;
                socket_.shutdown(ec); //Code blocks here indefinitely
        }
}

Any reasons why the socket_.shutdown( ) blocks. How could I specify a timeout such that the shutdown( ) returns back after some time? Any other way of handling this? ( I know there is async_shutdown( ) but I prefer using shutdown( ) blocking handler)


Any help would be greatly appreciated.


Regards,

Fariya


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: shutdown( ) blocks forever

Boost - Users mailing list
On Wed, Dec 30, 2020 at 6:27 AM Fariya F via Boost-users
<[hidden email]> wrote:
> I see that the call to ssl socket member function shutdown() blocks sometimes forever

You are mixing synchronous and asynchronous operations on the same
socket, which is generally disallowed. Use async_shutdown instead, and
also use a timer to close the socket after some time period (say, 30
seconds).

Regards
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: shutdown( ) blocks forever

Boost - Users mailing list
Hi,

Thanks. A couple of more questions:
a) Could you help me with a sample code which handles shutdown gracefully (async shutdown + timer) for iterative servers?
b) I have also seen issues where the code hangs just like the shutdown() when I invoke socket_.lowest_layer().cancel(). Is this expected?
c) Is this what is the code to be put in the async shutdown handler?
     socket_.lowest_layer().close(ignored_ec); 

Regards,
Fariya

On Wed, Dec 30, 2020 at 8:04 PM Vinnie Falco <[hidden email]> wrote:
On Wed, Dec 30, 2020 at 6:27 AM Fariya F via Boost-users
<[hidden email]> wrote:
> I see that the call to ssl socket member function shutdown() blocks sometimes forever

You are mixing synchronous and asynchronous operations on the same
socket, which is generally disallowed. Use async_shutdown instead, and
also use a timer to close the socket after some time period (say, 30
seconds).

Regards

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: shutdown( ) blocks forever

Boost - Users mailing list


On Wed, 30 Dec 2020 at 15:47, Fariya F via Boost-users <[hidden email]> wrote:
Hi,

Thanks. A couple of more questions:
a) Could you help me with a sample code which handles shutdown gracefully (async shutdown + timer) for iterative servers?
b) I have also seen issues where the code hangs just like the shutdown() when I invoke socket_.lowest_layer().cancel(). Is this expected?
c) Is this what is the code to be put in the async shutdown handler?
     socket_.lowest_layer().close(ignored_ec); 

a) Funnily enough I answered a similar question today on timed asio udp reception, but it's the same principle.
That answer is here:
In this case you'd substitute the async_receive with stream.async_shutdown and you'd cancel() the lowest_layer

b) It depends what was pending on the lowest layer. In general I would not expect to see anything hang in an asynchronous system. Could it be that you are mixing sync and async in more than one place?

c) yes, that should do it.
 

Regards,
Fariya

On Wed, Dec 30, 2020 at 8:04 PM Vinnie Falco <[hidden email]> wrote:
On Wed, Dec 30, 2020 at 6:27 AM Fariya F via Boost-users
<[hidden email]> wrote:
> I see that the call to ssl socket member function shutdown() blocks sometimes forever

You are mixing synchronous and asynchronous operations on the same
socket, which is generally disallowed. Use async_shutdown instead, and
also use a timer to close the socket after some time period (say, 30
seconds).

Regards
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Richard Hodges
office: +442032898513
home: +376841522
mobile: +376380212


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users