Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
886 views
in Technique[技术] by (71.8m points)

c++ - Crash : terminate called after throwing an instance of 'std::system_error' what(): Resource deadlock avoided

I have a simple client /server application the code of which is mentioned below. Please run the server in one shell and the client in another shell in linux. First start the server and then the client. When the server is done with it's work, it crashes with following exception:

terminate called after throwing an instance of 'std::system_error' what(): Resource deadlock avoided

This happens from the line m_thread->join() from inside the function Service::HandleClient I have no clue on what's going on.. Can someone please check the code.. I just want that the server application should also get closed correctly the way the client application got closed.

**Server Code : **

#include <boost/asio.hpp>

#include <thread>
#include <atomic>
#include <memory>
#include <iostream>

using namespace boost;

class Service {
public:
    Service(){}

    void StartHandligClient(
        std::shared_ptr<asio::ip::tcp::socket> sock) {

        m_thread.reset(new std::thread (([this, sock]() {
            HandleClient(sock);
        })) );

    }

private:
    void HandleClient(std::shared_ptr<asio::ip::tcp::socket> sock) {
        while(1)
        {
            try {
                asio::streambuf request;
                std::cout << "Waiting to read 
";
                asio::read_until(*sock.get(), request, '
');

                std::string s( (std::istreambuf_iterator<char>(&request)), std::istreambuf_iterator<char>() );
                std::cout << "Server got : " << s << "
";

                // Emulate request processing.
                int i = 0;
                while (i != 1000000)
                    i++;

                std::this_thread::sleep_for(
                        std::chrono::milliseconds(500));

                // Sending response.
                std::string response = "Response
";
                asio::write(*sock.get(), asio::buffer(response));
            }
            catch (system::system_error &e) {
                boost::system::error_code ec = e.code();
                if(ec == asio::error::eof)
                {
                    std::cout << "Breaking loop 
";
                    break;
                }
                std::cout << "Error occured! Error code = "
                    << e.code() << ". Message: "
                    << e.what();
            }
        }

        m_thread->join();

        // Clean-up.
        delete this;
    }
    std::unique_ptr<std::thread> m_thread;
};

class Acceptor {
public:
    Acceptor(asio::io_service& ios, unsigned short port_num) :
        m_ios(ios),
        m_acceptor(m_ios,
        asio::ip::tcp::endpoint(
        asio::ip::address_v4::any(),
        port_num))
    {
        m_acceptor.listen();
    }

    void Accept() {
        std::cout << "Server Accept() 
" << std::flush;
        std::shared_ptr<asio::ip::tcp::socket>
            sock(new asio::ip::tcp::socket(m_ios));

        std::cout << "BEFORE calling acceptor's accept function 
" << std::flush;
        m_acceptor.accept(*sock.get());
        std::cout << "AFTER calling acceptor's accept function 
" << std::flush;


        (new Service)->StartHandligClient(sock);
    }

    void close()
    {
        std::cout << "Inside Acceptor.close() 
" << std::flush;
        m_acceptor.close();
    }

private:
    asio::io_service& m_ios;
    asio::ip::tcp::acceptor m_acceptor;
};

class Server {
public:
    Server() : m_stop(false) {}

    void Start(unsigned short port_num) {
        m_thread.reset(new std::thread([this, port_num]() {
            Run(port_num);
        }));
    }

    void Stop() {
        m_stop.store(true);
        m_thread->join();
    }

private:
    void Run(unsigned short port_num) {
        Acceptor acc(m_ios, port_num);

        while (!m_stop.load()) {
            std::cout << "Server accept
" << std::flush;
            acc.Accept();
        }
        acc.close();
    }

    std::unique_ptr<std::thread> m_thread;
    std::atomic<bool> m_stop;
    asio::io_service m_ios;
};

int main()
{
    unsigned short port_num = 3333;

    try {
        Server srv;
        srv.Start(port_num);

        std::this_thread::sleep_for(std::chrono::seconds(4));

        srv.Stop();
    }
    catch (system::system_error &e) {
        std::cout << "Error occured! Error code = "
            << e.code() << ". Message: "
            << e.what();
    }

    return 0;
}

**Client Code : **

#include <boost/asio.hpp>
#include <iostream>

using namespace boost;

class SyncTCPClient {
public:
    SyncTCPClient(const std::string& raw_ip_address,
        unsigned short port_num) :
        m_ep(asio::ip::address::from_string(raw_ip_address),
        port_num),
        m_sock(m_ios) {

        m_sock.open(m_ep.protocol());
    }

    void connect() {
        m_sock.connect(m_ep);
    }

    void close() {
        m_sock.shutdown(
            boost::asio::ip::tcp::socket::shutdown_both);
        m_sock.close();
    }

    std::string emulateLongComputationOp(
        unsigned int duration_sec) {

        std::string request = "EMULATE_LONG_COMP_OP "
            + std::to_string(duration_sec)
            + "
";

        sendRequest(request);
        return receiveResponse();
    };

private:
    void sendRequest(const std::string& request)
    {
        std::cout << "Inside sendRequest : " << request << "
";
        asio::write(m_sock, asio::buffer(request));
    }

    std::string receiveResponse() {
        asio::streambuf buf;
        asio::read_until(m_sock, buf, '
');

        std::istream input(&buf);

        std::string response;
        std::getline(input, response);

        return response;
    }

private:
    asio::io_service m_ios;

    asio::ip::tcp::endpoint m_ep;
    asio::ip::tcp::socket m_sock;
};

int main()
{
    const std::string raw_ip_address = "127.0.0.1";
    const unsigned short port_num = 3333;

    try {
        SyncTCPClient client(raw_ip_address, port_num);

        // Sync connect.
        client.connect();

        std::cout << "Sending request to the server... " << std::endl;
        std::string response = client.emulateLongComputationOp(10);

        std::cout << "Response received: " << response << std::endl;
        sleep(2);

        // Close the connection and free resources.
        client.close();
    }
    catch (system::system_error &e) {
        std::cout << "Error occured! Error code = " << e.code()
            << ". Message: " << e.what();

        return e.code().value();
    }

    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

@sehe .. can you run the code and let me know how to overcome the crash that I mentioned ? – Nishant Sharma

Actually, no I won't. The problem has already been analyzed: you can't join the current thread (it would deadlock).

But I can do something better:

Grabbing my crystal ball, I can guess you got this example from a particular book, named Boost.Asio C++ Network Programming Cookbook1, around page 139.

I recognized it after a while when I added up all the code smells (delete this and m_stop.load() tipped me over the edge).

The good news is, I reviewed that code before:

ASIO example code closing socket before it should

You can probably profit from the particular comments I made there.

1 from packtpub: https://www.packtpub.com/application-development/boostasio-c-network-programming-cookbook


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...