Правильно убивает asio stable_timer после отключения - PullRequest
1 голос
/ 21 апреля 2019

Я написал асинхронную реализацию сокета SSL с использованием автономного asio и пытаюсь восстановить соединение после сброса / закрытия соединения сервером. Я довольно новичок в библиотеке asio, поэтому, пожалуйста, потерпите меня.

Поток, который вызывает io_context::run, остается заблокированным даже после отключения из-за steady_timer. Моя логика close() отвечает за сброс ресурсов сокета, а также за попытку уничтожить таймер. Вот как выглядит мой код прямо сейчас:

Создание моей асинхронной работы:

timer.async_wait(std::bind(&ssl_socket::heartbeat, this));

В моем close() методе:

timer.expires_at(std::chrono::steady_clock::now());
timer.cancel();

Согласно документам boost , cancel() следует:

Отмена любых асинхронных операций, ожидающих на таймере.

Возможно, я неверно истолковал это, но я бы подумал, что это также отменяет асинхронную работу, связанную с io_context, но это не так. io_context::run никогда не освобождается и создает тупик.

Вот так выглядит мой обработчик таймера:

void ssl_socket::heartbeat() {
    spdlog::get("console")->trace("heartbeat called");

    if (connected_) {
        write(heartbeat_token);
        spdlog::get("console")->trace("heartbeat sent");
    }

    timer.expires_at(std::chrono::steady_clock::now() + std::chrono::seconds(heartbeat_interval));
    timer.async_wait(std::bind(&ssl_socket::heartbeat, this));

}

Я бы хотел, чтобы обработчику не приходилось проверять, должен ли он обновить таймер и позволить close() справиться с этим (если это возможно).

1 Ответ

1 голос
/ 21 апреля 2019

Вы игнорируете код ошибки.

Согласно документам надбавки, метод cancel () должен:

Отменить любые асинхронные операции, ожидающие по таймеру.

Это немного вводит в заблуждение.Когда вы прочитаете полное описание функции cancel, вы увидите:

Эта функция принудительно завершает любые незавершенные асинхронные операции ожидания с таймером.Обработчик для каждой отмененной операции будет вызываться с кодом ошибки boost::asio::error::operation_aborted.

Это означает, что ваш обработчик будет вызываться функцией отмены, и поскольку ваш обработчик просто переустанавливает значение expiry-время и снова ждет, цикл никогда не заканчивается.Вам нужно проверить код ошибки и просто выйти из цикла, если он установлен.

if(error) return;
...