0
以下の状況を考慮してください:1つのスレッド(Aと呼ぶことができます)が初期化し、ソケットの状態をlisten()
に設定してからaccept()
で待機します。接続はAソケットに到着し、accept()
は有効なfdを返します。取得されたfdがスレッドBで実行可能な呼び出し可能オブジェクトに渡されます。fdの読み取り(read()
を使用)が失敗し、errno
が9 EBADFD
に設定されています。スレッドAはBにjoin()
を呼び出します.Bが生成されず、fdが使用されている場合(同じ呼び出し可能オブジェクト経由でも)、読み取りは失敗せずに完了します。どうして?以下は、この状況を示すためのコードです。スレッドを持つLinuxソケットファイル記述子
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;
}
あなたの問題とは無関係ですが、次に行うことがそれを待つだけの場合は、なぜスレッドを作成するのですか?スレッドの作成と 'join'呼び出しの間に何か他のことをしていると思いますか?たぶん、問題は*あなたが私たちを見せない部分ですか? –
これをどのように修正するのか興味があります。私は問題を(私の答えごとに)見つけ出すのに十分なC++を知っていますが、それを修正することはできません。 'std :: thread job(std :: ref(dm))'を書くだけで十分だろうかと思います。 – Alnitak
@Alnitak私はクイックテストを実行し、 'std :: ref()'は問題を解決します。しかし、私は "大規模"で十分ではないか、この 'join()'呼び出しを取り除こうとすると思います。 – Ufo