Сообщение Re[5]: Отладка Boost::Asio от 06.12.2019 16:27
Изменено 06.12.2019 16:38 netch80
Re[5]: Отладка Boost::Asio
Здравствуйте, prrt, Вы писали:
P>Может, изначальная проблема кроется в том, что acceptor перестал делать accept? В этом случае как-то так и должно ведь быть, клиенты остались, а серверные соединения исчезли.
С принудительно проактивным построением ASIO действительно проблема, что если в каком-то случае забыть "взвести курок" на следующий "выстрел", то оно так и останется ничего не делающим — а добиться этого банально: не все ветки исполнения проследил; поймал исключение и не сделал finally (его аналог для C++) для запроса следующего действия по сокету; и так далее.
Спастись от этого можно только дисциплиной кодирования — или дополнительными костылями по всему коду.
У меня в одном проекте работал самопальный аналог ASIO, сделанный по модели питоновского asyncore. В этом случае у объекта — оболочки сокета есть переопределяемые методы readable и writable, которые он дёргает перед каждым циклом ожидания и проверки поступления данных. Там с этим значительно проще: сам фреймворк обязан вызвать эти методы — и он их вызывает, осталось только подставлять правильные данные. Но это почти реактивное построение, а не проактивное.
Думаю, проверить можно так: сделайте где-то переменную (достаточно bool) с логикой типа:
Тогда в отладчике можно будет проверять этот флаг; не стоит => ошибка в вашем коде; стоит => проблема в ASIO.
P> Правда непонятно, почему asio в этом случае не реагирует на сигналы, зарегистрированные в этом же io_service. Точнее, как попадешь — иногда реагирует, иногда нет.
P>И если так, то по какой причине это может быть? Нигде в логах нет никаких сообщений, никаких ошибок.
Ну в таком сложном звере ошибки вполне возможны. Но это надо ещё доказать.
P>Может, изначальная проблема кроется в том, что acceptor перестал делать accept? В этом случае как-то так и должно ведь быть, клиенты остались, а серверные соединения исчезли.
С принудительно проактивным построением ASIO действительно проблема, что если в каком-то случае забыть "взвести курок" на следующий "выстрел", то оно так и останется ничего не делающим — а добиться этого банально: не все ветки исполнения проследил; поймал исключение и не сделал finally (его аналог для C++) для запроса следующего действия по сокету; и так далее.
Спастись от этого можно только дисциплиной кодирования — или дополнительными костылями по всему коду.
У меня в одном проекте работал самопальный аналог ASIO, сделанный по модели питоновского asyncore. В этом случае у объекта — оболочки сокета есть переопределяемые методы readable и writable, которые он дёргает перед каждым циклом ожидания и проверки поступления данных. Там с этим значительно проще: сам фреймворк обязан вызвать эти методы — и он их вызывает, осталось только подставлять правильные данные. Но это почти реактивное построение, а не проактивное.
Думаю, проверить можно так: сделайте где-то переменную (достаточно bool) с логикой типа:
void Zuka::requestAccept() {
if (mAcceptRequested) { return; }
mIOService.async_accept(..., [this](const boost::system::error_code &ec) { cbAccept(ec); });
mAcceptRequested = true;
}
void Zuka::cbAccept(const boost::system::error_code &ec) {
if (ec) { разберётесь сами; }
mAcceptRequested = false;
... обработка ...
if (!mShutdownRequested) { requestAccept(); }
}
Тогда в отладчике можно будет проверять этот флаг; не стоит => ошибка в вашем коде; стоит => проблема в ASIO.
P> Правда непонятно, почему asio в этом случае не реагирует на сигналы, зарегистрированные в этом же io_service. Точнее, как попадешь — иногда реагирует, иногда нет.
P>И если так, то по какой причине это может быть? Нигде в логах нет никаких сообщений, никаких ошибок.
Ну в таком сложном звере ошибки вполне возможны. Но это надо ещё доказать.
Re[5]: Отладка Boost::Asio
Здравствуйте, prrt, Вы писали:
P>Может, изначальная проблема кроется в том, что acceptor перестал делать accept? В этом случае как-то так и должно ведь быть, клиенты остались, а серверные соединения исчезли.
С принудительно проактивным построением ASIO действительно проблема, что если в каком-то случае забыть "взвести курок" на следующий "выстрел", то оно так и останется ничего не делающим — а добиться этого банально: не все ветки исполнения проследил; поймал исключение и не сделал finally (его аналог для C++) для запроса следующего действия по сокету; и так далее.
Спастись от этого можно только дисциплиной кодирования — или дополнительными костылями по всему коду.
У меня в одном проекте работал самопальный аналог ASIO, сделанный по модели питоновского asyncore. В этом случае у объекта — оболочки сокета есть переопределяемые методы readable и writable, которые он дёргает перед каждым циклом ожидания и проверки поступления данных. Там с этим значительно проще: сам фреймворк обязан вызвать эти методы — и он их вызывает, осталось только подставлять правильные данные. Но это почти реактивное построение, а не проактивное.
Думаю, проверить можно так: сделайте где-то переменную (достаточно bool) с логикой типа:
Тогда в отладчике можно будет проверять этот флаг; не стоит => ошибка в вашем коде; стоит => проблема в ASIO.
P> Правда непонятно, почему asio в этом случае не реагирует на сигналы, зарегистрированные в этом же io_service. Точнее, как попадешь — иногда реагирует, иногда нет.
P>И если так, то по какой причине это может быть? Нигде в логах нет никаких сообщений, никаких ошибок.
Ну в таком сложном звере ошибки вполне возможны. Но это надо ещё доказать.
UPD: если и сигналы зависают, то тут что-то более хитрое. Но всё равно стоит попробовать
P>Может, изначальная проблема кроется в том, что acceptor перестал делать accept? В этом случае как-то так и должно ведь быть, клиенты остались, а серверные соединения исчезли.
С принудительно проактивным построением ASIO действительно проблема, что если в каком-то случае забыть "взвести курок" на следующий "выстрел", то оно так и останется ничего не делающим — а добиться этого банально: не все ветки исполнения проследил; поймал исключение и не сделал finally (его аналог для C++) для запроса следующего действия по сокету; и так далее.
Спастись от этого можно только дисциплиной кодирования — или дополнительными костылями по всему коду.
У меня в одном проекте работал самопальный аналог ASIO, сделанный по модели питоновского asyncore. В этом случае у объекта — оболочки сокета есть переопределяемые методы readable и writable, которые он дёргает перед каждым циклом ожидания и проверки поступления данных. Там с этим значительно проще: сам фреймворк обязан вызвать эти методы — и он их вызывает, осталось только подставлять правильные данные. Но это почти реактивное построение, а не проактивное.
Думаю, проверить можно так: сделайте где-то переменную (достаточно bool) с логикой типа:
void Zuka::requestAccept() {
if (mAcceptRequested) { return; }
mIOService.async_accept(..., [this](const boost::system::error_code &ec) { cbAccept(ec); });
mAcceptRequested = true;
}
void Zuka::cbAccept(const boost::system::error_code &ec) {
if (ec) { разберётесь сами; }
mAcceptRequested = false;
... обработка ...
if (!mShutdownRequested) { requestAccept(); }
}
Тогда в отладчике можно будет проверять этот флаг; не стоит => ошибка в вашем коде; стоит => проблема в ASIO.
P> Правда непонятно, почему asio в этом случае не реагирует на сигналы, зарегистрированные в этом же io_service. Точнее, как попадешь — иногда реагирует, иногда нет.
P>И если так, то по какой причине это может быть? Нигде в логах нет никаких сообщений, никаких ошибок.
Ну в таком сложном звере ошибки вполне возможны. Но это надо ещё доказать.
UPD: если и сигналы зависают, то тут что-то более хитрое. Но всё равно стоит попробовать