ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-10-09 09:17:20  阅读:331  来源: 互联网

标签:c boost boost-asio


我有一个简单的客户端/服务器应用程序,其代码如下所述.
请在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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有