通知父级线程终止

时间:2014-02-13 10:05:14

标签: c multithreading pthreads

这不是代码中的任何错误,而是要了解如何完成以下条件。我看到了类似的问题herehere,但没有采用任何特定的方法来做这件事。

考虑以下代码部分:

....

pthread_create(&Receiver,NULL,ReceiveFromServer,(void*)&ClientSoc);
sending =1;
while (sending)
{
     SHOW_PROMPT;
     gets(message);
     memcpy(Packet.data,message,MAX_DATA_LENGTH);
     if (SetCommand(&Packet,message) == CMD_EXT)
         sending = 0;
     send(ClientSoc,&Packet,PACKET_SIZE,0);
}
close(ClientSoc);
pthread_join(Receiver,NULL);
return 0;
....

ReceiveFromServer函数:

void* ReceiveFromServer(void* ClientSoc)
{
    int receiving =1;
    int Status;
    strPacket Packet;
    while(receiving)
    {
        if(recv(*(int*)ClientSoc,&Packet,PACKET_SIZE,0)>0)
        {
            ParseReply(Packet);
            SHOW_PROMPT;
        }
        if(GET_COMMAND(Packet.Header) == CMD_EXT)
            receiving = 0;
    }
    return NULL;
}

假设所有内容都已正确声明或定义。 <
因此,线程根据从服务器接收的数据终止,但发送方仍然循环,因为它不知道接收方被终止。发件人只会根据用户输入(特定词语,如“退出”)退出循环。
如何通知父母线程正在终止?
我试图使sending全局并从线程内部进行更改,但它不起作用。

3 个答案:

答案 0 :(得分:2)

获取CMD_EXT时,关闭“ReceiveFromServer”线程中的套接字。发送线程应该很快得到消息 - send()调用将返回错误。

答案 1 :(得分:1)

在父主循环中,替换:

   while (sending)

使用:

   while (sending && pthread_kill(Receiver, 0) != ESRCH)

这将检查Receiver线程是否存在。有关详细信息,请参阅How do you query a pthread to see if it is still running?

但请注意,How do I determine if a pthread is alive?强调您无法为 分离的 主题执行此操作。并且http://man7.org/linux/man-pages/man3/pthread_kill.3.html表示:

  

POSIX.1-2008建议如果某个实现在其生命周期结束后检测到使用了线程ID,则pthread_kill()应该返回错误ESRCH。在可以检测到无效线程ID的情况下,glibc实现返回此错误。但请注意,POSIX表示尝试使用其生命周期已结束的线程ID会产生未定义的行为,并且在调用pthread_kill()时尝试使用无效的线程ID会导致分段错误。

当你获得CMD_EXT时,在ReceiveFromServer线程中关闭套接字可能也会起作用,因为Are parallel calls to send/recv on the same socket valid?似乎表明POSIX套接字是线程安全的。但是R.强烈建议Is closesocket thread safe?反对它。 RHEL5 Linux man 2 close声明:

  

关闭文件描述符可能是不明智的,因为它们可能在同一进程中的其他线程中被系统调用使用。由于文件描述符可能会被重复使用,因此有一些模糊的竞争条件可能会导致意外的副作用。

     

在处理套接字时,你必须确保在另一个线程上没有recv(2)仍然阻塞它,否则它可能永远阻塞,因为不会再通过套接字发送消息。在关闭插座之前,请务必使用shutdown(2)关闭连接的所有部分。

此外,您可能还希望将gets(message)替换为非阻塞等效项,以处理在您等待人工输入时对等方异步发送CMD_EXT的情况。

当然,你需要添加套接字错误处理,但这超出了这个问题的范围。

答案 2 :(得分:0)

也许您可以尝试在父循环中使用pthread_tryjoin_np(我从未使用它)来检测线程是否已完成。据我所知,它只适用于linux。