【问题标题】:Notify parent about thread terminating通知父线程终止
【发布时间】:2014-03-12 03:20:06
【问题描述】:

这不是代码中的任何错误,而是要了解如何完成以下条件。我见过类似的问题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设为全局并从线程内部更改它,但它不起作用。

【问题讨论】:

  • @suufang,我提到我看到了这个问题,但这并没有回答这种情况。
  • 发布一个完整的示例来演示您的问题。 假设所有内容都已正确声明或定义 - 该假设让您 100% 陷入麻烦。
  • 我不明白。如果接收方根据从发送方收到的内容终止,则发送方应该提前知道接收方将终止,因此发送方可以在向接收方发送终止数据后自行终止,不是吗?
  • @alk,这里的接收者和发送者来自客户端程序。它接收并发送到服务器程序。所以这个发送者不知道这个接收者会得到什么,因为那是由服务器发送的。
  • Ahok,我明白了.. 一定是我这边暂时的脑瘫。您可能想按照下面的答案选择 Martin 的方法。

标签: c multithreading pthreads


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    在父级的主循环中,替换:

       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 的情况。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2011-02-27
        • 2014-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-07
        • 1970-01-01
        • 2015-12-25
        • 1970-01-01
        相关资源
        最近更新 更多