ghostinecatnewyear
ghostinecatnewyear

Reputation: 301

Segmentation fault in handlers with shared_ptr's

I am trying to make a proxy that works properly only for the first session in one execution of app. It catches SIGSEGV trying to handle the second one.

It works next way:

The problem is when we start the app and the first client tries to use proxy, it works fine (let it be clients connect to proxy consistently e.g. first one got its data, disconnection occured and only then the second one connects). But when the second one tries to connect after this, execution can not even reach the handleAccept and catches SIGSEGV in __atomic_add function in atomicity.h (I am working in Linux).

I can not understand either I make handlers incorrectly, use shared_ptr's incorrectly, or both.

run is called once after creating Proxy object to make it accept and handle client connections:

void Proxy::run() // create the very first session and keep waiting for other connections
{
    auto newSession = std::make_shared<Session>(ioService_);

    acceptor_.async_accept(
        newSession->getClientSocket(),
        [&](const boost::system::error_code &error) // handler is made according to boost documentation
        {
            handleAccept(newSession, error);
        }
    );

    ioService_.run();
}

handleAccept does almost the same thing but also makes session start transferring data between client and end server:

void Proxy::handleAccept(std::shared_ptr<Session> session, const boost::system::error_code &error) // handle the new connection and keep waiting other ones
{
    if (!error)
    {
        session->connectToServer(serverEndpoint_);
        session->run(); // two more shared_ptr's to session are appeared here and we just let it go (details are further)
    }

    auto newSession = std::make_shared<Session>(ioService_);

    acceptor_.async_accept(
        newSession->getClientSocket(),
        [&](const boost::system::error_code &error)
        {
            handleAccept(newSession, error);
        }
    );
}

Session contains two Socket objects (server and client) each of which has shared_ptr to it. When each of them will have done all actions or some error will have occured, they reset their shared_ptr's to session so it is deallocated.

Upvotes: 0

Views: 242

Answers (1)

Evgeny
Evgeny

Reputation: 1072

Why you use/catch local variable by reference in handleAccept(...) ?:

 acceptor_.async_accept(
        newSession->getClientSocket(),
        [&](const boost::system::error_code &error)
        {
            handleAccept(newSession, error);
        }
    );

Would you like to use:

 acceptor_.async_accept(
        newSession->getClientSocket(),
        [this, newSession](const boost::system::error_code &error)
        {
            handleAccept(newSession, error);
        }
    );

The lambda will be run after function will be completed, and local variable newSession will be destroied before that.

Upvotes: 3

Related Questions