Reputation: 2292
I want to establish a socket connection in one method and use this connection in another method of a class. While in the first method (where I establish the connection) I can read and write from and to the socket as much as I want, in the second method I always get a Bad file descriptor
error. Note that I use version 1.65.1
of Boost.
I created a small reproducible example (I added some logs for clarification):
code.h
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class SocketManager {
tcp::socket *sock;
boost::asio::io_service *io_service;
tcp::acceptor *acceptor;
public:
virtual void initialize(); // works
virtual void evaluate(); // fails
};
code.cc
#include "code.h"
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
int main() {
SocketManager sm;
sm.initialize();
sm.evaluate();
return 0;
}
void SocketManager::initialize() {
boost::asio::io_service _io_service;
io_service = &_io_service;
tcp::acceptor a(*io_service, tcp::endpoint(tcp::v4(), 1337));
acceptor = &a;
tcp::socket sock_(*io_service);
sock = &sock_;
a.accept(*sock);
char data[1024];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error)
throw boost::system::system_error(error); // No Error here!
boost::asio::write(*sock, boost::asio::buffer(data, length));
cout << io_service->stopped() << endl; // prints 0
cout << acceptor->is_open() << endl; // prints 1
cout << sock->is_open() << endl; // prints 1
}
void SocketManager::evaluate() {
cout << io_service->stopped() << endl; // prints 0
cout << acceptor->is_open() << endl; // prints 1
cout << sock->is_open() << endl; // prints 1
char data[1024];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error)
throw boost::system::system_error(error); // Error: "Bad file descriptor"
}
Output of the code above when used with a client:
root@5531547d4baf:/cpp# ./a.out
0
1
1
0
1
1
terminate called after throwing an instance of 'boost::system::system_error'
what(): Bad file descriptor
Aborted
Note that the code that throws the error is the exact same code in both methods (in the first one it works without any error and in the second one it throws a Bad file descriptor
error).
I suspect that the io_service
is no longer valid when switching to the new function, so I have already experimented with the associated poll
and run
functions without success.
I also tried to replace the boost::asio::buffer
with a boost::asio::mutable_buffer
and a boost::asio::mutable_buffer
. However, the exact same code works in the first method, so I suspect that the function calls are alright!
Upvotes: 0
Views: 221
Reputation: 12889
As per the comment sock
, io_service
and acceptor
members of SocketManager
are initialized to point to local variables within SocketManager::initialize
. When that completes you then have dangling pointers.
I don't see any reason to use pointers at all here. Just make them non-pointer data members and initialize them in a constructor (untested)...
class SocketManager {
boost::asio::io_service io_service;
tcp::acceptor acceptor;
tcp::socket sock;
public:
SocketManager ()
: acceptor(io_service, tcp::endpoint(tcp::v4(), 1337))
, sock(io_service)
{}
...
};
Note that the io_service
member is declared first as it must be initialized before sock
and acceptor
.
Upvotes: 1