Hi dear stackoverflow community,
I have a problem only in certain compilation settings (which indicates some kind of UB, but I decided to tag this question as boost-asio since it might involve knowledge about asio specifics). Note that I use the current git version of the standalone asio library.
First let me drop some snippets - the complete code is here: http://ift.tt/1K14ssb (note that the CMakeLists.txt is very hacky and might need fixing in case you would want to compile it).
I have a test echo server (tcp, async) in examples/echo_server.cpp:
[snip...]
int main (int argc, char const* argv[]) {
try {
if (argc != 2) {
std::cerr << "Usage: echo_server <port>\n";
return 1;
}
asio::io_context io_context;
magellan::server server;
server.accept<echo_session>(io_context, 9003);
io_context.run();
} catch (std::exception& e) {
std::cerr << e.what() << "\n";
}
}
Obviously the interesting parts are the server and echo_session classes; however the latter seems to work correctly, so I am gonna drop the server class here. The include/server.hpp:
#ifndef MAGELLAN_SERVER_HPP_
#define MAGELLAN_SERVER_HPP_
#include "session.hpp"
namespace magellan {
class server {
public:
[snip typedefs...]
public:
server();
virtual ~server();
template <typename Session>
void accept(asio::io_context& io_context, short port);
[snip comments...]
};
} // magellan
#include "server.ipp"
#endif /* MAGELLAN_SERVER_HPP_ */
... and the include/server.ipp:
#include <iostream>
namespace magellan {
template <typename Session>
inline void
server::accept(asio::io_context& io_context, short port) {
using asio::ip::tcp;
asio::spawn(io_context, [&](asio::yield_context yield) {
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));
for (;;) {
asio::error_code ec;
tcp::socket socket(io_context);
acceptor.async_accept(socket, yield[ec]);
if (!ec) {
auto session = std::make_shared<Session>(std::move(socket));
session->start();
}
}
});
}
[snip comments...]
} // magellan
Now the interesting thing is that the async_accept opens a tcp socket iff I compile with -O1, -O2 and -O3, but not with -O0. I checked this via:
> ss -a | grep 9003
296:tcp LISTEN 0 128 *:9003 *:*
When compiled with -O0 the socket is never opened. I also checked that the service is still running via an io_context::work instance.
My best guess (admittedly lacking confidence) is that boost coroutine does something different with -O0. It may also be worth mentioning that if I use the commented out code in server.ipp it also won't open sockets (no matter what compilation settings):
template <typename Session>
inline void
server::accept(asio::io_context& io_context, short port) {
using asio::ip::tcp;
accept<Session>(io_context, port, [](tcp::socket s) {
return std::make_shared<Session>(std::move(s));
});
}
template <typename Session, typename Func>
void
server::accept(asio::io_context& io_context, short port, Func&& factory) {
using asio::ip::tcp;
asio::spawn(io_context, [&](asio::yield_context yield) {
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));
for (;;) {
asio::error_code ec;
tcp::socket socket(io_context);
acceptor.async_accept(socket, yield[ec]);
if (!ec) {
auto session = factory(std::move(socket));
session->start();
} else {
std::cout << "failed accept" << "\n";
}
}
});
}
This was my initial problem and I attributed it to a copied instead of moved socket until I arrived at the -O0 flag problem.
I am pretty lost at this point as I have no idea how to debug these async processes in general but am still confident the actual answer to my question will be in some way embarassing ;)
Hope you have a hint for me.
Best, Richard
Aucun commentaire:
Enregistrer un commentaire