Ошибка сегментации в обработчиках с shared_ptr - PullRequest
0 голосов
/ 17 января 2020

Я пытаюсь создать прокси, который работает правильно только для первого сеанса в одном запуске приложения. Он ловит SIGSEGV, пытаясь обработать второй.

Он работает следующим образом:

  • клиент подключается
  • прокси подключается к конечному серверу (уникальное подключение для каждого сеанс)
  • прокси отправляет данные на сервер, получает обработанные данные с сервера и отправляет обработанные данные клиенту
  • прокси разрывает соединение с сервером и клиентом

Проблема заключается в том, что Когда мы запускаем приложение, и первый клиент пытается использовать прокси-сервер, он работает нормально (пусть это будут клиенты, которые последовательно подключаются к прокси-серверу, например, первый получил свои данные, произошло отключение, и только после этого второй подключился). Но когда второй пытается подключиться после этого, выполнение не может даже достичь handleAccept и ловит SIGSEGV в __atomic_add функции в atomicity.h (я работаю в Linux).

Я не могу понять, я делаю обработчики неправильно, неправильно использую shared_ptr, или и то и другое.

run вызывается один раз после создания объекта Proxy, чтобы он принимал и обрабатывал клиентские подключения:

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 делает почти то же самое, но также запускает сеанс передачи данных между клиентом и конечным сервером:

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 содержит два объекта Socket (сервер и клиент ) каждый из которых имеет shared_ptr к нему. Когда каждое из них выполнит все действия или произойдет какая-либо ошибка, они reset их shared_ptr в сеансе, поэтому он освобожден.

1 Ответ

3 голосов
/ 17 января 2020

Почему вы используете / перехватываете локальную переменную по ссылке в handleAccept (...)?:

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

Хотите использовать:

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

Будет запущена лямбда после того, как функция будет завершена, и локальная переменная newSession будет уничтожена до этого.

...