其他分享
首页 > 其他分享> > c-崩溃:抛出’std :: system_error’what()实例后调用终止,避免资源死锁

c-崩溃:抛出’std :: system_error’what()实例后调用终止,避免资源死锁

作者:互联网

我有一个简单的客户端/服务器应用程序,其代码如下所述.
请在Linux中的一个shell中运行服务器,在另一个shell中运行客户端.
首先启动服务器,然后启动客户端.
服务器完成工作后,会崩溃,但以下异常:

抛出’std :: system_error’实例后调用终止
  what():避免资源死锁

这是从函数Service :: HandleClient内部的m_thread-> join()行发生的
我对正在发生的事情一无所知.有人可以检查代码吗.我只希望服务器应用程序也应该以关闭客户端应用程序的方式正确关闭.

**服务器代码:**

#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 \n";
                asio::read_until(*sock.get(), request, '\n');

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

                // 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\n";
                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 \n";
                    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() \n" << 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 \n" << std::flush;
        m_acceptor.accept(*sock.get());
        std::cout << "AFTER calling acceptor's accept function \n" << std::flush;


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

    void close()
    {
        std::cout << "Inside Acceptor.close() \n" << 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\n" << 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;
}

**客户代码:**

#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)
            + "\n";

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

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

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

        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;
}

解决方法:

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

实际上,不,我不会.该问题已得到分析:您无法加入当前线程(这将导致死锁).

但我可以做得更好:

拿起我的水晶球,我猜你是从一本名为139 000左右的特殊书《 Boost.Asio C++ Network Programming Cookbook》中得到的.

一段时间后,当我将所有代码气味加总时,我意识到了这一点(删除此代码,然后m_stop.load()在边缘提示我).

好消息是,我之前检查过该代码:

ASIO example code closing socket before it should

您可能可以从我在那发表的评论中受益.

¹来自packtpub:https://www.packtpub.com/application-development/boostasio-c-network-programming-cookbook

标签:c,boost,boost-asio
来源: https://codeday.me/bug/20191009/1878157.html