title: Proper way to handle SIGTERM with multiple threads
body: <p>I have a multi threaded program on Raspberry in which I want to handle SIGTERM and shut everything down gracefully. The issue is that I have a background thread that has called <code>recvfrom()</code> on a blocking socket. As per my understanding from the man pages, if I exit my handler all the system calls should be woken up and return with -1 and <code>errno</code> set to <code>EINTR</code>. However in my case the <code>recvfrom</code> call keeps hanging.</p>
  
  <p>1) In general am I understanding this right, that all threads that have blocking system calls that are able to be woken up by a signal should wake up in this scenario?
  2) Could it be that the operating system is setting some special signal mask on my thead?</p>
  
  <p>The interresting part is that I am using the VideoCore primitives, not pthread, maybe that could be the cause? Here is a small test example:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  #include &lt;cstdlib&gt;
  #include &lt;cstring&gt;
  #include &lt;errno.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;signal.h&gt;
  
  
  #include "interface/vcos/vcos.h"
  
  void SignalHandler(int nSignalNumber)
  {
      std::cout &lt;&lt; "received signal " &lt;&lt; nSignalNumber &lt;&lt; std::endl;
  }
  
  void* ThreadMain(void* pArgument)
  {
      int nSocket = socket(AF_INET, SOCK_DGRAM, 0);
      if (nSocket &gt;= 0)
      {
          sockaddr_in LocalAddress;
          memset(&amp;LocalAddress, 0, sizeof(LocalAddress));
          LocalAddress.sin_family = AF_INET;
          LocalAddress.sin_addr.s_addr = INADDR_ANY;
          LocalAddress.sin_port = htons(1234);
          if (bind(nSocket, reinterpret_cast&lt;sockaddr *&gt;(&amp;LocalAddress), sizeof(LocalAddress)) == 0)
          {
              sockaddr_in SenderAddress;
              socklen_t nSenderAddressSize = sizeof(SenderAddress);
              unsigned char pBuffer[512];
              std::cout &lt;&lt; "calling recvfrom()" &lt;&lt; std::endl;
              int nBytesReceived = recvfrom(nSocket, pBuffer, sizeof(pBuffer), 0, reinterpret_cast&lt;struct sockaddr *&gt;(&amp;SenderAddress), &amp;nSenderAddressSize);
              if (nBytesReceived == -1)
              {
                  if (errno == EINTR)
                  {
                      std::cout &lt;&lt; "recvfrom() was interrupred by a signal" &lt;&lt; std::endl;
                  }
                  else
                  {
                      std::cout &lt;&lt; "recvfrom() failed with " &lt;&lt; errno &lt;&lt; std::endl;
                  }
              }
          }
          else
          {
              std::cout &lt;&lt; "bind() failed with " &lt;&lt; errno &lt;&lt; std::endl;
          }
          close(nSocket);
      }
      else
      {
          std::cout &lt;&lt; "socket() failed with " &lt;&lt; errno &lt;&lt; std::endl;
      }
      return NULL;
  }
  
  int main(int argc, char** argv)
  {
      struct sigaction SignalAction;
      memset(&amp;SignalAction, 0, sizeof(SignalAction));
      SignalAction.sa_handler = SignalHandler;
      sigaction(SIGTERM, &amp;SignalAction, NULL);
      VCOS_THREAD_T Thread;
      VCOS_STATUS_T nVcosStatus = vcos_thread_create(&amp;Thread, "", NULL, ThreadMain, NULL);
      if (nVcosStatus == VCOS_SUCCESS)
      {
          void* pData = NULL;
          vcos_thread_join(&amp;Thread, &amp;pData);
      }
      else
      {
          std::cout &lt;&lt; "vcos_thread_create() failed with " &lt;&lt; nVcosStatus &lt;&lt; std::endl;
      }
      return EXIT_SUCCESS;
  }
  </code></pre>
  
  <p>It can be compiled like this:</p>
  
  <pre><code>g++ test.cpp -I/opt/vc/include -L/opt/vc/lib -lvcos  -o test
  </code></pre>
  
  <p>When I run it and then call <code>kill</code> on the running instance the output is:</p>
  
  <pre><code>calling recvfrom()
  received signal 15
  </code></pre>
  
  <p>and the process hangs. I'll try if a pthread behaves differently.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Ok I updated the sample to spawn a pthread thread as well and that one is not quitting as well. So I assume the signals are not populated to all threads?</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  #include &lt;cstdlib&gt;
  #include &lt;cstring&gt;
  #include &lt;errno.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;signal.h&gt;
  #include &lt;pthread.h&gt;
  
  #include "interface/vcos/vcos.h"
  
  void SignalHandler(int nSignalNumber)
  {
      std::cout &lt;&lt; "received signal " &lt;&lt; nSignalNumber &lt;&lt; std::endl;
  }
  
  void* ThreadMain(void* pArgument)
  {
      const char* pThreadType = reinterpret_cast&lt;const char*&gt;(pArgument);
      int nSocket = socket(AF_INET, SOCK_DGRAM, 0);
      if (nSocket &gt;= 0)
      {
          sockaddr_in LocalAddress;
          memset(&amp;LocalAddress, 0, sizeof(LocalAddress));
          LocalAddress.sin_family = AF_INET;
          LocalAddress.sin_addr.s_addr = INADDR_ANY;
          LocalAddress.sin_port = htons(pThreadType[0] * 100);
          if (bind(nSocket, reinterpret_cast&lt;sockaddr *&gt;(&amp;LocalAddress), sizeof(LocalAddress)) == 0)
          {
              sockaddr_in SenderAddress;
              socklen_t nSenderAddressSize = sizeof(SenderAddress);
              unsigned char pBuffer[512];
              std::cout &lt;&lt; "calling recvfrom()" &lt;&lt; std::endl;
              int nBytesReceived = recvfrom(nSocket, pBuffer, sizeof(pBuffer), 0, reinterpret_cast&lt;struct sockaddr *&gt;(&amp;SenderAddress), &amp;nSenderAddressSize);
              if (nBytesReceived == -1)
              {
                  if (errno == EINTR)
                  {
                      std::cout &lt;&lt; "recvfrom() was interrupred by a signal" &lt;&lt; std::endl;
                  }
                  else
                  {
                      std::cout &lt;&lt; "recvfrom() failed with " &lt;&lt; errno &lt;&lt; std::endl;
                  }
              }
          }
          else
          {
              std::cout &lt;&lt; "bind() failed with " &lt;&lt; errno &lt;&lt; std::endl;
          }
          close(nSocket);
      }
      else
      {
          std::cout &lt;&lt; "socket() failed with " &lt;&lt; errno &lt;&lt; std::endl;
      }
      std::cout &lt;&lt; pThreadType &lt;&lt; " thread is exiting" &lt;&lt; std::endl;
      return NULL;
  }
  
  int main(int argc, char** argv)
  {
      struct sigaction SignalAction;
      memset(&amp;SignalAction, 0, sizeof(SignalAction));
      SignalAction.sa_handler = SignalHandler;
      sigaction(SIGTERM, &amp;SignalAction, NULL);
      VCOS_THREAD_T VcosThread;
      VCOS_STATUS_T nVcosStatus = vcos_thread_create(&amp;VcosThread, "", NULL, ThreadMain, const_cast&lt;char*&gt;("vcos"));
      bool bJoinVcosThread = false;
      if (nVcosStatus == VCOS_SUCCESS)
      {
          bJoinVcosThread = true;
      }
      else
      {
          std::cout &lt;&lt; "vcos_thread_create() failed with " &lt;&lt; nVcosStatus &lt;&lt; std::endl;
      }
      pthread_t PthreadThread;
      int nPthreadStatus = pthread_create(&amp;PthreadThread, NULL, ThreadMain, const_cast&lt;char*&gt;("pthread"));
      bool bJoinPthreadThread = false;
      if (nPthreadStatus == 0)
      {
          bJoinPthreadThread = true;
      }
      else
      {
          std::cout &lt;&lt; "pthread_create() failed with " &lt;&lt; nPthreadStatus &lt;&lt; std::endl;
      }
      if (bJoinVcosThread)
      {
          void* pData = NULL;
          vcos_thread_join(&amp;VcosThread, &amp;pData);
      }
      if (bJoinPthreadThread)
      {
          void* pData = NULL;
          pthread_join(PthreadThread, &amp;pData);
      }
      return EXIT_SUCCESS;
  }
  </code></pre>