系统V msgrcv在线程中阻塞

时间:2017-07-21 06:12:37

标签: c multithreading pthreads signals message-queue

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

   /*! \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没有收到信号? 如果我将线程作为主循环,那么它会返回并且应用程序成功退出。

1 个答案:

答案 0 :(得分:1)

如果信号被发送到进程,则一个未阻止它的线程将处理它,但未指定它将是哪个线程。你说你没有在所有其他线程上阻止static CDUVariable Baud() { return { baud, "0"}; } 。因此,您看到的行为最可能的解释是信号由主线程处理,而不是调用SIGINT的线程。

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

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