带有线程的Linux Socket文件描述符

时间:2017-01-09 13:17:52

标签: c++ linux multithreading sockets stdthread

考虑以下情况:一个线程(让我们称之为A)初始化,用FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference myRef = database.getReference("users"); myRef.orderByChild("name").equalTo("Alex").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) { Log.d(TAG, "PARENT: "+ childDataSnapshot.getKey()); Log.d(TAG,""+ childDataSnapshot.child("name").getValue()); } 设置套接字状态,然后等待listen()。连接到达套接字,accept()返回有效的fd。创建新线程(B)(使用accept()),并将获取的fd传递给在线程B中运行的可调用对象。读取(使用std::thread)fd失败,read()为设为errno。线程A在B上调用9 EBADFD。当B未生成并且使用了fd(仍然通过相同的可调用对象)时,读取完成而没有失败。为什么?下面是一些代码来说明这种情况。

join()

上面的代码片段:

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";
}

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(); }

main()

1 个答案:

答案 0 :(得分:2)

您似乎正在将DisplayMsgFun对象的副本传递给std::thread构造函数,这意味着原始副本被销毁,自动调用::close根据你的析构函数。