consider following situation: One thread (lets call it A) initialises, sets socket state with listen() and then wait with accept(). Connection arrives to A socket, accept() returns valid fd. New thread (B) is created (using std::thread), and acquired fd is passed to a callable object witch runs in thread B. Reading (using read()) for fd fails and errno is set to 9 EBADFD. Thread A calls join() on B. When B is not spawned and fd is used (still via same callable object) read completes without failure. Why? Below is some code to illustrate this situation.
BaseFun::BaseFun(char* bufferAdr, int socket):
socket_fd(socket)
buffer(bufferAdr)
{}
BaseFun::~BaseFun()
{
close(socket_fd);
}
char* BaseFun::buffer_read()
{
if(read(socket_fd, buffer, BUFF_SIZE-1) < 0) {
std::cout<<"ERROR while READ\n"<<"ERRNO: "<<errno<<"\n"<<"FD: "<<socket_fd<<"\n";
}
return buffer;
}
DisplayMsgFun::DisplayMsgFun(char* buffer, int socket) :
BaseFun(buffer, socket)
{}
void DisplayMsgFunFun::operator()()
{
std::cout<<"Message:\n\t"<<buffer_read()<<"\nEND\n";
}
Snippet where above is called:
void Server::server_run()
{
sockaddr_in client_addr;
socklen_t c_len = sizeof(client_addr);
client_fd = accept(sock_fd, (sockaddr*)&client_addr, &c_len);
DisplayMsgFun dm(server_buffers->front().data(), client_fd);
std::thread job(dm);
job.join();
}
And main()
int main()
{
Server srv(PORT);
if (srv.server_create()) {
std::cout << "Server bind!\n";
srv.server_run();
}
else {
std::cout << "Bind fail! ERRNO: "<<errno<<"\n";
return -1;
}
return 0;
}
1 Answer 1
You appear to be passing a copy of the DisplayMsgFun object to the std::thread constructor, which means that the original copy gets destroyed, automatically calling ::close per your destructor.
Comments
Explore related questions
See similar questions with these tags.
joincall? Maybe the problem is that part (that you don't show us)?std::thread job(std::ref(dm))would be sufficient.std::ref()solves problem. But I guess that will not be sufficient in "large scale", or when I will try to get rid off thisjoin()call.dmdoesn't get destroyed when it goes out of scope when yourserver_runfunction finishes while the thread is still trying to use that object. Hmm...std::thread job(dm)only the new instance of the object maintains the file descriptor (and gains responsibility for closing it) and the original learns that it no longer has to (perhaps by settingsocket_fdto a negative value to signal that)