线程中的 System V msgrcv 阻塞

System V msgrcv blocking in thread

我有一个应用程序,它有信号处理程序并创建了一个线程来处理消息队列。 下面是信号处理程序,

   /*! \Register handle on SIGINT. */
   signal(SIGINT, CloseHandler);

VOID CloseHandler(INT32 sig)
{
if(sig == SIGINT)
gAppExitFlag = 1;
return;
}

我已经创建了一个可连接的线程来接收消息队列,

      /* Initialize and set thread detached attribute */
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  if(0 != (count = pthread_create(&ModemDetectionHandel, &attr, &ModemDetectionOperation, (void *)&gAppContext)))
  {
     DS3_ERROR(DS3_TELEMETRY_APP, "Error in creating thread ModemDetectionOperation");
  }

在线程中,我创建了一个消息队列并使用 msgflg 0 调用 msgrcv。 因此它将阻塞直到收到任何消息。 现在,当我发送 SIGINT 进行处理但 msgrcv 不返回并在 msgrcv 中阻塞线程时。

我的应用程序卡在加入线程中。

根据 msgrcv 手册页“*调用进程捕获信号。在这种情况下,系统调用失败,errno 设置为 EINTR。(msgrcv() 在被中断后永远不会自动重新启动 信号处理程序,无论在建立信号处理程序时 SA_RESTART 标志的设置如何。)"

为什么thread/msgrcv收不到信号? 如果我将线程作为主循环然后它返回并且应用程序成功退出。

如果一个信号被发送到一个进程,一个没有阻塞它的线程将处理它,但未指定这是哪个线程。您说您没有在所有其他线程上阻塞 SIGINT。因此,对您看到的行为最可能的解释是信号由主线程处理,而不是调用 msgrcv.

的线程

要解决此问题,您可以在除调用 msgrcv 的线程之外的所有线程上阻塞 SIGINT。这将确保信号由该线程处理。

如果您有多个需要中断的线程,这将不起作用。在这种情况下,您可能需要为所有线程阻塞 SIGINT,并在特殊的中断处理线程中使用 sigwait 来接收 SIGINT 信号。然后该线程可以向所有需要中断的线程发送另一个信号(可能 SIGUSR1),每个这样的线程发送一个 pthread_kill。或者您也可以使用 pthread_cancel,具体取决于您的需要。