1

Im trying write tcp server. From boost guide link enter link description here. When im trying open acceptor - segmentation fault, IDE show me this line object_pool_access::prev(live_list_) = o; What im doing wrong? Im trying another way for example run threads for context but that doesnt work. Sometime when im try to fix i get this one message -

tpp.c:82: __pthread_tpp_change_priority: Assertion `new_prio == -1 || (new_prio >= fifo_min_prio && new_prio <= fifo_max_prio)' failed.
Aborted (core dumped)

The code is contained in the 1st file. Application class with io_context, he is here because ill use him in another parts of program:

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <memory>
using namespace boost::asio;
class api_application
{
public:
 virtual ~api_application() {}
 virtual void start() = 0;
 virtual boost::asio::io_context& get_context() = 0;
};
class application : public api_application
{
public:
 application();
 ~application() override {}
public:
 virtual void start() override;
 virtual boost::asio::io_context& get_context() override;
 
 void stop();
private:
 boost::asio::io_context _context;
 std::shared_ptr<tcp_server> _server;
};
application::application()
: 
_context(),
_server(std::make_shared<tcp_server>(*this))
{}
void application::start()
{
 _server->start();
 _context.run();
}
void application::stop()
{
 _context.stop();
}
boost::asio::io_context& application::get_context()
{
 return _context;
}

Networking code with error line:

class connection : public std::enable_shared_from_this<connection>
{
public:
 typedef std::shared_ptr<connection> con_ptr;
 static con_ptr create(boost::asio::io_context& io_service)
 {
 return con_ptr(new connection(io_service));
 }
 ip::tcp::socket& socket();
 void send(std::string message);
private:
 connection(boost::asio::io_context& io_service);
 void handle_write(const boost::system::error_code& err, size_t s);
private:
 ip::tcp::socket _socket;
};
class tcp_server
{
public:
 tcp_server(api_application& app);
 void start();
private:
 void start_accept();
 void handle_accept(connection::con_ptr new_connection, const boost::system::error_code& error);
 api_application& _app;
 ip::tcp::endpoint _endpoint;
 ip::tcp::acceptor _acceptor;
};
tcp_server::tcp_server(api_application& app)
:
_app(app), 
_endpoint(boost::asio::ip::address_v4::any(), 80),
_acceptor(app.get_context())
{}
void tcp_server::start()
{
 if(_acceptor.is_open())
 return;
 
 _acceptor.open(_endpoint.protocol()); // Here segfault
 _acceptor.set_option(ip::tcp::socket::reuse_address(true));
 
 _acceptor.bind(_endpoint);
 _acceptor.listen();
 start_accept();
}
void tcp_server::start_accept()
{
 connection::con_ptr new_connection =
 connection::create((boost::asio::io_context&)_acceptor.get_executor().context());
 _acceptor.async_accept(new_connection->socket(),
 boost::bind(&tcp_server::handle_accept, this, new_connection,
 boost::asio::placeholders::error));
}
void tcp_server::handle_accept(connection::con_ptr new_connection, const boost::system::error_code& error)
{
 if (!error)
 {
 new_connection->send("Success connection");
 }
 start_accept();
}
void connection::send(std::string message)
{
 boost::asio::async_write(_socket, boost::asio::buffer(message),
 boost::bind(&connection::handle_write, shared_from_this(),
 boost::asio::placeholders::error,
 boost::asio::placeholders::bytes_transferred));
}
connection::connection(boost::asio::io_context& io_service)
: _socket(io_service)
{}
int main(int argc, const char** argv)
{
 application app();
 app.start();
 return 0;
}
asked Jan 3, 2023 at 5:28
3
  • 1
    A minimal reproducible example must be Compilable, i.e. contain all required #include statemants. Commented Jan 3, 2023 at 5:32
  • Added includes. Commented Jan 3, 2023 at 12:16
  • @lbsmart still can't compile as your main starts out with a Most Vexing Parse Commented Jan 3, 2023 at 17:02

1 Answer 1

1

I found the likely issue while rewriting the code to avoid context references. See Update

I have no problem with the code, imagining the missing bits:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
#include <memory>
namespace asio = boost::asio;
using asio::ip::tcp;
using boost::system::error_code;
class connection : public std::enable_shared_from_this<connection> {
 public:
 typedef std::shared_ptr<connection> con_ptr;
 static con_ptr create(asio::io_context& io_service) {
 return con_ptr{new connection(io_service)};
 }
 tcp::socket& socket() { return _socket; }
 void send(std::string message);
 private:
 connection(asio::io_context& io_service);
 void handle_write(error_code err, size_t s) {
 std::cerr << "handle_write: " << err.message() << " " << s << std::endl;
 }
 private:
 tcp::socket _socket;
};
struct api_application {
 virtual ~api_application() {}
 virtual void start() = 0;
 virtual asio::io_context& get_context() = 0;
};
class tcp_server {
 public:
 tcp_server(api_application& app);
 void start();
 private:
 void start_accept();
 void handle_accept(connection::con_ptr new_connection,
 error_code error);
 api_application& _app;
 tcp::endpoint _endpoint;
 tcp::acceptor _acceptor;
};
class application : public api_application {
 public:
 application();
 ~application() override {}
 public:
 virtual void start() override;
 virtual asio::io_context& get_context() override;
 void stop();
 private:
 asio::io_context _context;
 std::shared_ptr<tcp_server> _server;
};
application::application()
 : _context()
 , _server(std::make_shared<tcp_server>(*this)) {}
void application::start() {
 _server->start();
 _context.run();
}
tcp_server::tcp_server(api_application& app)
 : _app(app)
 , _endpoint({}, 8989)
 , _acceptor(app.get_context()) {}
void tcp_server::start() {
 if (_acceptor.is_open())
 return;
 _acceptor.open(_endpoint.protocol()); // Here segfault
 _acceptor.set_option(tcp::acceptor::reuse_address(true));
 _acceptor.bind(_endpoint);
 _acceptor.listen();
 start_accept();
}
void tcp_server::start_accept() {
 connection::con_ptr new_connection = connection::create(
 (asio::io_context&)_acceptor.get_executor().context());
 _acceptor.async_accept(new_connection->socket(),
 boost::bind(&tcp_server::handle_accept, this,
 new_connection,
 asio::placeholders::error));
}
void tcp_server::handle_accept(connection::con_ptr new_connection,
 error_code error) {
 if (!error) {
 new_connection->send("Success connection");
 }
 start_accept();
}
void connection::send(std::string message) {
 async_write(_socket, asio::buffer(message),
 boost::bind(&connection::handle_write,
 shared_from_this(),
 asio::placeholders::error,
 asio::placeholders::bytes_transferred));
}
connection::connection(asio::io_context& io_service)
 : _socket(io_service) {}
void application::stop() { _context.stop(); }
asio::io_context& application::get_context() { return _context; }
int main() {
 application app;
 app.start();
}

Prints e.g.

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp
./a.out&
for a in {1..10}; do sleep 0.5; nc 127.0.0.1 8989 <<<"Hello world"; done
kill %1
Success connectionhandle_write: Success 18
handle_write: Success connectionSuccess 18
handle_write: Success Success connection18
Success connectionhandle_write: Success 18
Success connectionhandle_write: Success 18
Success connectionhandle_write: Success 18
Success connectionhandle_write: Success 18
Success connectionhandle_write: Success 18
Success connectionhandle_write: Success 18
Success connectionhandle_write: Success 18

Summary

Your problem is elsewhere. Permissions, exception handling, ODR, maybe you're not running the code you think you are.

Also, this code seems unnecessarily complicated and a bit dated (io_service has been deprecated for quite some time).

UPDATE

This is highly suspicious code

connection::con_ptr new_connection = connection::create( (asio::io_context&)_acceptor.get_executor().context());

If it works it is due to undocumented implementation details. It is technically Undefined Behaviour because it does a hard re-interpret-cast. Instead, just use the executor as intended!

auto new_connection = connection::create(_acceptor.get_executor());

Here's the whole thing reworked to avoid context references:

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
#include <memory>
namespace asio = boost::asio;
using asio::ip::tcp;
using boost::system::error_code;
class connection : public std::enable_shared_from_this<connection> {
 public:
 typedef std::shared_ptr<connection> con_ptr;
 static con_ptr create(asio::any_io_executor ex) {
 return con_ptr{new connection(ex)};
 }
 tcp::socket& socket() { return _socket; }
 void send(std::string message);
 private:
 connection(asio::any_io_executor ex);
 void handle_write(error_code err, size_t s) {
 std::cerr << "handle_write: " << err.message() << " " << s << std::endl;
 }
 private:
 tcp::socket _socket;
};
struct api_application {
 virtual ~api_application() {}
 virtual void start() = 0;
 virtual asio::any_io_executor get_executor() = 0;
};
class tcp_server {
 public:
 tcp_server(api_application& app);
 void start();
 private:
 void start_accept();
 void handle_accept(connection::con_ptr new_connection,
 error_code error);
 api_application& _app;
 tcp::endpoint _endpoint;
 tcp::acceptor _acceptor;
};
class application : public api_application {
 public:
 application();
 ~application() override {}
 public:
 virtual void start() override;
 virtual asio::any_io_executor get_executor() override;
 void stop();
 private:
 asio::io_context _context;
 std::shared_ptr<tcp_server> _server;
};
application::application()
 : _context()
 , _server(std::make_shared<tcp_server>(*this)) {}
void application::start() {
 _server->start();
 _context.run();
}
tcp_server::tcp_server(api_application& app)
 : _app(app)
 , _endpoint({}, 8989)
 , _acceptor(app.get_executor()) {}
void tcp_server::start() {
 if (_acceptor.is_open())
 return;
 _acceptor.open(_endpoint.protocol()); // Here segfault
 _acceptor.set_option(tcp::acceptor::reuse_address(true));
 _acceptor.bind(_endpoint);
 _acceptor.listen();
 start_accept();
}
void tcp_server::start_accept() {
 auto new_connection = connection::create(_acceptor.get_executor());
 _acceptor.async_accept(new_connection->socket(),
 boost::bind(&tcp_server::handle_accept, this,
 new_connection,
 asio::placeholders::error));
}
void tcp_server::handle_accept(connection::con_ptr new_connection,
 error_code error) {
 if (!error) {
 new_connection->send("Success connection");
 }
 start_accept();
}
void connection::send(std::string message) {
 async_write(_socket, asio::buffer(message),
 boost::bind(&connection::handle_write,
 shared_from_this(),
 asio::placeholders::error,
 asio::placeholders::bytes_transferred));
}
connection::connection(asio::any_io_executor ex) : _socket(ex) {}
void application::stop() { _context.stop(); }
asio::any_io_executor application::get_executor() {
 return _context.get_executor();
}
int main() {
 application app;
 app.start();
}

Still printing the same Live On Coliru

answered Jan 3, 2023 at 17:12
Sign up to request clarification or add additional context in comments.

1 Comment

I found the likely issue while rewriting the code to avoid context references. See Update

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.