2017-01-09 118 views
0

請考慮以下情況:一個線程(讓我們稱之爲A)初始化,將套接字狀態設置爲listen(),然後等待accept()。連接到達A插座,accept()返回有效的fd。創建新線程(B)(使用std::thread),並將獲取的fd傳遞給在線程B中運行的可調用對象。使用read()讀取fd失敗,並且errno設置爲9 EBADFD。線程A在B上調用join()。當B未生成且使用fd(仍然通過相同的可調用對象)時,讀取完成而沒有失敗。爲什麼?下面是一些代碼來說明這種情況。Linux Socket文件描述符與線程

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

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; 
} 
+0

與你的問題無關,但爲什麼創建一個線程,如果你接下來要做的只是等待它呢?我假設你在線程創建和'join'調用之間做了一些其他的事情?也許問題是*那部分(你沒有告訴我們)? –

+0

我很想看看你如何解決這個問題。我知道足夠的C++來發現問題(根據我的答案),但不能解決它。我想知道是否只寫'std :: thread job(std :: ref(dm))'就足夠了。 – Alnitak

+0

@Alnitak我運行了快速測試,'std :: ref()'解決了問題。但我想這在「大規模」中還不夠,或者我會試圖擺脫這種「join()」調用。 – Ufo

回答

2

你似乎是經過DisplayMsgFun對象的副本std::thread構造,這意味着原始副本被破壞,每個des都自動調用::close tructor。