signal handler and multithreading












1















I know that signal is a way of communication between CPU and OS kernel. A signal can interrupt the sequence of instructions, execute the handler and go back to the sequence of instructions.



Here is a piece of description of this link:




When a signal that is being caught is handled by a process, the normal
sequence of instructions being executed by the process is temporarily
interrupted by the signal handler. The process then continues
executing, but the instructions in the signal handler are now
executed. If the signal handler returns, the process continues
executing the normal sequence of instructions it was executing when
the signal was caught.




Here is my test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
while(1)
{
cout<<"main"<<endl;
sleep(2);
}
return 0;
}


I execute it and if I press ctrl+C, int will be printed and then I have to wait for 5 seconds, no matter how many times ctrl+C I pressed while waiting for the 5 seconds, nothing happened.



Then I make another test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
thread t1((){while(1){cout<<"t1"<<endl; sleep(2);}});
thread t2((){while(1){cout<<"t2"<<endl; sleep(2);}});
t1.join();
t2.join();

return 0;
}


For this code, I found that I could press ctrl+C three times continually and three int would be printed, then I have to wait for about 5 seconds.



So it seems that the first ctrl+C interrupts the t1 thread, the second interrupts the t2 thread and the third interrupts the main thread.



So signal only interrupt thread instead of the whole process if there are multi-threading?










share|improve this question


















  • 3





    Your code invokes undefined behavior. Per footnote 183 of the C standard: "Thus, a signal handler cannot, in general, call standard library functions." POSIX allows the calling of async-signal-safe functions from within a signal handler. Using cout and calling sleep() are not async-signal-safe.

    – Andrew Henle
    Dec 19 '18 at 11:29








  • 1





    You don't want to have to handle signals that way. Not ever.

    – curiousguy
    Dec 19 '18 at 11:43






  • 1





    man7.org/linux/man-pages/man7/signal.7.html

    – Oliv
    Dec 19 '18 at 11:59











  • @AndrewHenle Yes, you are right. But I need to print something to debug, so I think I have no choice. Using non-reentrant functions in signal handler can be undefined behavior. At least for the code above, it works as expected.

    – Yves
    Dec 20 '18 at 1:16






  • 1





    @Yves On a POSIX system: write( STDOUT_FILENO, buffer, strlen( buffer ) ); Or STDERR_FILENO, if you prefer. Build a C-style string, then use write().

    – Andrew Henle
    Dec 20 '18 at 10:33


















1















I know that signal is a way of communication between CPU and OS kernel. A signal can interrupt the sequence of instructions, execute the handler and go back to the sequence of instructions.



Here is a piece of description of this link:




When a signal that is being caught is handled by a process, the normal
sequence of instructions being executed by the process is temporarily
interrupted by the signal handler. The process then continues
executing, but the instructions in the signal handler are now
executed. If the signal handler returns, the process continues
executing the normal sequence of instructions it was executing when
the signal was caught.




Here is my test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
while(1)
{
cout<<"main"<<endl;
sleep(2);
}
return 0;
}


I execute it and if I press ctrl+C, int will be printed and then I have to wait for 5 seconds, no matter how many times ctrl+C I pressed while waiting for the 5 seconds, nothing happened.



Then I make another test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
thread t1((){while(1){cout<<"t1"<<endl; sleep(2);}});
thread t2((){while(1){cout<<"t2"<<endl; sleep(2);}});
t1.join();
t2.join();

return 0;
}


For this code, I found that I could press ctrl+C three times continually and three int would be printed, then I have to wait for about 5 seconds.



So it seems that the first ctrl+C interrupts the t1 thread, the second interrupts the t2 thread and the third interrupts the main thread.



So signal only interrupt thread instead of the whole process if there are multi-threading?










share|improve this question


















  • 3





    Your code invokes undefined behavior. Per footnote 183 of the C standard: "Thus, a signal handler cannot, in general, call standard library functions." POSIX allows the calling of async-signal-safe functions from within a signal handler. Using cout and calling sleep() are not async-signal-safe.

    – Andrew Henle
    Dec 19 '18 at 11:29








  • 1





    You don't want to have to handle signals that way. Not ever.

    – curiousguy
    Dec 19 '18 at 11:43






  • 1





    man7.org/linux/man-pages/man7/signal.7.html

    – Oliv
    Dec 19 '18 at 11:59











  • @AndrewHenle Yes, you are right. But I need to print something to debug, so I think I have no choice. Using non-reentrant functions in signal handler can be undefined behavior. At least for the code above, it works as expected.

    – Yves
    Dec 20 '18 at 1:16






  • 1





    @Yves On a POSIX system: write( STDOUT_FILENO, buffer, strlen( buffer ) ); Or STDERR_FILENO, if you prefer. Build a C-style string, then use write().

    – Andrew Henle
    Dec 20 '18 at 10:33
















1












1








1








I know that signal is a way of communication between CPU and OS kernel. A signal can interrupt the sequence of instructions, execute the handler and go back to the sequence of instructions.



Here is a piece of description of this link:




When a signal that is being caught is handled by a process, the normal
sequence of instructions being executed by the process is temporarily
interrupted by the signal handler. The process then continues
executing, but the instructions in the signal handler are now
executed. If the signal handler returns, the process continues
executing the normal sequence of instructions it was executing when
the signal was caught.




Here is my test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
while(1)
{
cout<<"main"<<endl;
sleep(2);
}
return 0;
}


I execute it and if I press ctrl+C, int will be printed and then I have to wait for 5 seconds, no matter how many times ctrl+C I pressed while waiting for the 5 seconds, nothing happened.



Then I make another test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
thread t1((){while(1){cout<<"t1"<<endl; sleep(2);}});
thread t2((){while(1){cout<<"t2"<<endl; sleep(2);}});
t1.join();
t2.join();

return 0;
}


For this code, I found that I could press ctrl+C three times continually and three int would be printed, then I have to wait for about 5 seconds.



So it seems that the first ctrl+C interrupts the t1 thread, the second interrupts the t2 thread and the third interrupts the main thread.



So signal only interrupt thread instead of the whole process if there are multi-threading?










share|improve this question














I know that signal is a way of communication between CPU and OS kernel. A signal can interrupt the sequence of instructions, execute the handler and go back to the sequence of instructions.



Here is a piece of description of this link:




When a signal that is being caught is handled by a process, the normal
sequence of instructions being executed by the process is temporarily
interrupted by the signal handler. The process then continues
executing, but the instructions in the signal handler are now
executed. If the signal handler returns, the process continues
executing the normal sequence of instructions it was executing when
the signal was caught.




Here is my test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
while(1)
{
cout<<"main"<<endl;
sleep(2);
}
return 0;
}


I execute it and if I press ctrl+C, int will be printed and then I have to wait for 5 seconds, no matter how many times ctrl+C I pressed while waiting for the 5 seconds, nothing happened.



Then I make another test:



void func(int p)
{
cout<<"int"<<endl;
sleep(5);
}

int main()
{
signal(SIGINT, func);
thread t1((){while(1){cout<<"t1"<<endl; sleep(2);}});
thread t2((){while(1){cout<<"t2"<<endl; sleep(2);}});
t1.join();
t2.join();

return 0;
}


For this code, I found that I could press ctrl+C three times continually and three int would be printed, then I have to wait for about 5 seconds.



So it seems that the first ctrl+C interrupts the t1 thread, the second interrupts the t2 thread and the third interrupts the main thread.



So signal only interrupt thread instead of the whole process if there are multi-threading?







c++ c linux multithreading signals






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 19 '18 at 11:22









YvesYves

2,77432363




2,77432363








  • 3





    Your code invokes undefined behavior. Per footnote 183 of the C standard: "Thus, a signal handler cannot, in general, call standard library functions." POSIX allows the calling of async-signal-safe functions from within a signal handler. Using cout and calling sleep() are not async-signal-safe.

    – Andrew Henle
    Dec 19 '18 at 11:29








  • 1





    You don't want to have to handle signals that way. Not ever.

    – curiousguy
    Dec 19 '18 at 11:43






  • 1





    man7.org/linux/man-pages/man7/signal.7.html

    – Oliv
    Dec 19 '18 at 11:59











  • @AndrewHenle Yes, you are right. But I need to print something to debug, so I think I have no choice. Using non-reentrant functions in signal handler can be undefined behavior. At least for the code above, it works as expected.

    – Yves
    Dec 20 '18 at 1:16






  • 1





    @Yves On a POSIX system: write( STDOUT_FILENO, buffer, strlen( buffer ) ); Or STDERR_FILENO, if you prefer. Build a C-style string, then use write().

    – Andrew Henle
    Dec 20 '18 at 10:33
















  • 3





    Your code invokes undefined behavior. Per footnote 183 of the C standard: "Thus, a signal handler cannot, in general, call standard library functions." POSIX allows the calling of async-signal-safe functions from within a signal handler. Using cout and calling sleep() are not async-signal-safe.

    – Andrew Henle
    Dec 19 '18 at 11:29








  • 1





    You don't want to have to handle signals that way. Not ever.

    – curiousguy
    Dec 19 '18 at 11:43






  • 1





    man7.org/linux/man-pages/man7/signal.7.html

    – Oliv
    Dec 19 '18 at 11:59











  • @AndrewHenle Yes, you are right. But I need to print something to debug, so I think I have no choice. Using non-reentrant functions in signal handler can be undefined behavior. At least for the code above, it works as expected.

    – Yves
    Dec 20 '18 at 1:16






  • 1





    @Yves On a POSIX system: write( STDOUT_FILENO, buffer, strlen( buffer ) ); Or STDERR_FILENO, if you prefer. Build a C-style string, then use write().

    – Andrew Henle
    Dec 20 '18 at 10:33










3




3





Your code invokes undefined behavior. Per footnote 183 of the C standard: "Thus, a signal handler cannot, in general, call standard library functions." POSIX allows the calling of async-signal-safe functions from within a signal handler. Using cout and calling sleep() are not async-signal-safe.

– Andrew Henle
Dec 19 '18 at 11:29







Your code invokes undefined behavior. Per footnote 183 of the C standard: "Thus, a signal handler cannot, in general, call standard library functions." POSIX allows the calling of async-signal-safe functions from within a signal handler. Using cout and calling sleep() are not async-signal-safe.

– Andrew Henle
Dec 19 '18 at 11:29






1




1





You don't want to have to handle signals that way. Not ever.

– curiousguy
Dec 19 '18 at 11:43





You don't want to have to handle signals that way. Not ever.

– curiousguy
Dec 19 '18 at 11:43




1




1





man7.org/linux/man-pages/man7/signal.7.html

– Oliv
Dec 19 '18 at 11:59





man7.org/linux/man-pages/man7/signal.7.html

– Oliv
Dec 19 '18 at 11:59













@AndrewHenle Yes, you are right. But I need to print something to debug, so I think I have no choice. Using non-reentrant functions in signal handler can be undefined behavior. At least for the code above, it works as expected.

– Yves
Dec 20 '18 at 1:16





@AndrewHenle Yes, you are right. But I need to print something to debug, so I think I have no choice. Using non-reentrant functions in signal handler can be undefined behavior. At least for the code above, it works as expected.

– Yves
Dec 20 '18 at 1:16




1




1





@Yves On a POSIX system: write( STDOUT_FILENO, buffer, strlen( buffer ) ); Or STDERR_FILENO, if you prefer. Build a C-style string, then use write().

– Andrew Henle
Dec 20 '18 at 10:33







@Yves On a POSIX system: write( STDOUT_FILENO, buffer, strlen( buffer ) ); Or STDERR_FILENO, if you prefer. Build a C-style string, then use write().

– Andrew Henle
Dec 20 '18 at 10:33














3 Answers
3






active

oldest

votes


















3














INTRODUCTION



First of all each thread has its own mask that specifies which signals it is listening to. When a thread is created it inherits the mask of the thread that is creating it (let me call it the parent thread) that is active when pthread_create is called.



Generally it is better that if a thread is listening to a signal then the others should not, unless you want to have many threads that do the same stuff (for example when processing a connection request in a server to process many requests simultaneously). In this way you always know which thread is processing the signal. Otherwise you do not have any idea which thread is receiving the signal and which part of the program is executing: it becomes impossible to debug (an example is your own question).



To change the mask of the child thread that is being created from the parent thread you create a new mask, you set it active, create a new thread with pthread_create and then in the parent thread set the previous mask active again (see the code at the end of the answer).



EDIT: According to this post it is better to use sigaction() instead of signal. In modern systems signal() is implemented with sigaction() so there should not be any difference. However if its old implementation is used, problems might arise.



ANSWER




So signal only interrupt thread instead of the whole process if there
are multi-threading?




NO: Signals are just signals, they do not do anything. Actions associated to signals have the power to do stuff, including stopping the program or terminating the thread. Each signal has a default action associated and the default action for SIGINT is to interrupt the process.



With you handler you are overwriting the default action. So it will not stop the program anymore but it will do what you have specified in the thread function.



In the first case you have only one thread, the main one, which is an infinite loop, it always catch the signal as long as he is alive so that's why the behavior. If you resend the signal, the signal is momentarily blocked until the signal handler ends the execution. Nevertheless if many signals are sent while the handler is executing, you can loose some signals.
In fact as explained here, blocked signals are set to pending, but not queued. The term pending means that the operating system remembers that there is a signal waiting to be delivered at the next opportunity by setting a flag, and not queued means that it does this by setting a flag somewhere, but not by keeping an exact record of how many signals have arrived.
So if the signals is sent once, 5 times or more (try to press CTRL+C more times with your program: I have tried) while the signal handler is executing it produces the exactly same behaviour.



In your second case you have 3 threads: the main one, t1, and t2: all of them are enabled to see the signal SIGINT and all of them have associated the same signal handler. If you press 3 times one after the other all three of them will execute the handler: that is why you don't see any delay. If you press very very fast though and more than 3 times (the number of threads listening to that signal) I think you will see something similar to the first behaviour.



I will end my answer with the code I posted in a question where I was setting masks so that some signals were caught only by the main thread:



int main()
{
int err;
sigset_t omask, mask;
pthread_t thread_motionSensor;
pthread_t thread_tempReading;
pthread_t thread_platformPost;

printf("Created threads IDsn");

...
if (signal(SIGINT, sig_handler)==SIG_ERR)
printf("Error on recording SIGINT HANDLERn");

/*Create a new mask to block all signals for the following thread*/
sigfillset(&mask);
pthread_sigmask(SIG_SETMASK, &mask, &omask);
printf("Trying to create threadsn");
if ((err = pthread_create (&thread_motionSensor, NULL, task1, NULL))!=0)
{
printf("Thread 1 not created: error %dn", err);
err_exit((const char)err, "pthread_create error");
}
printf("Thread 1 created. Trying to create Thread 2n");
if((err = pthread_create (&thread_tempReading, NULL, task2, NULL))!=0)
{
printf("Thread 2 not created: error %dn", err);
err_exit((const char)err, "pthread_create error");
}
printf("Thread 2 created. Trying to create Thread 3n");
if ((err = pthread_create (&thread_platformPost, NULL, task3, NULL))!=0)
{
printf("Thread 3 not created: error %d %dn", err);
err_exit((const char)err, "pthread_create error");
}
printf("Thread 3 createdn");
/*The main thread must block the SIGALRM but catch SIGINT
SIGQUIT, SIGTERM, SIgkILL*/
/*empty the omask set from all signals */
sigemptyset(&omask);
/*add the signals to the omask*/
sigaddset(&omask, SIGINT);
sigaddset(&omask, SIGQUIT);
sigaddset(&omask, SIGKILL);
sigaddset(&omask, SIGTERM);
/*unblock all signals in omask*/
pthread_sigmask(SIG_UNBLOCK, &omask, NULL);
printf("Main thread waiting for signaln");
/*pause will stop the main thread until any signal not blocked by omask will be received*/
pause();
printf("Exit signal received: cancelling threadsn");

pthread_cancel(thread_motionSensor);
pthread_cancel(thread_tempReading);
pthread_cancel(thread_platformPost);
pthread_join(thread_motionSensor, NULL);
pthread_join(thread_tempReading, NULL);
pthread_join(thread_platformPost, NULL);
printf("Exiting from main thread and processn");
exit(0);
}





share|improve this answer


























  • +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

    – Louis Langholtz
    Dec 27 '18 at 15:04











  • Thanks... I will check them and see if I can improve it.

    – Francesco Boi
    Dec 27 '18 at 15:30



















1














No matter how many threads the process has, some thread catches the signal and runs the signal handler while the other threads (if any) go on about their business. The signal is sent to the process, but what the process does when it gets the signal is dependent on how the process, and the threads in, configured its signal handlers.



The full rules are quite complicated and I think it's safe to say that very few programmers bother to full understand them and generally avoid signals except for very limited purposes. See here for more details.






share|improve this answer































    1















    So signal only interrupt thread instead of the whole process if there are multi-threading?




    Yes. A signal interrupts a single thread of execution. At least according to the POSIX standard. C standard itself doesn't specify behaviour of processes or threads.



    If a signal is generated for a multi threaded process as opposed to being generated for particular thread, the signal will be delivered to exactly one of the threads belonging to that process (unless the signal is blocked by all threads).






    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53850202%2fsignal-handler-and-multithreading%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      INTRODUCTION



      First of all each thread has its own mask that specifies which signals it is listening to. When a thread is created it inherits the mask of the thread that is creating it (let me call it the parent thread) that is active when pthread_create is called.



      Generally it is better that if a thread is listening to a signal then the others should not, unless you want to have many threads that do the same stuff (for example when processing a connection request in a server to process many requests simultaneously). In this way you always know which thread is processing the signal. Otherwise you do not have any idea which thread is receiving the signal and which part of the program is executing: it becomes impossible to debug (an example is your own question).



      To change the mask of the child thread that is being created from the parent thread you create a new mask, you set it active, create a new thread with pthread_create and then in the parent thread set the previous mask active again (see the code at the end of the answer).



      EDIT: According to this post it is better to use sigaction() instead of signal. In modern systems signal() is implemented with sigaction() so there should not be any difference. However if its old implementation is used, problems might arise.



      ANSWER




      So signal only interrupt thread instead of the whole process if there
      are multi-threading?




      NO: Signals are just signals, they do not do anything. Actions associated to signals have the power to do stuff, including stopping the program or terminating the thread. Each signal has a default action associated and the default action for SIGINT is to interrupt the process.



      With you handler you are overwriting the default action. So it will not stop the program anymore but it will do what you have specified in the thread function.



      In the first case you have only one thread, the main one, which is an infinite loop, it always catch the signal as long as he is alive so that's why the behavior. If you resend the signal, the signal is momentarily blocked until the signal handler ends the execution. Nevertheless if many signals are sent while the handler is executing, you can loose some signals.
      In fact as explained here, blocked signals are set to pending, but not queued. The term pending means that the operating system remembers that there is a signal waiting to be delivered at the next opportunity by setting a flag, and not queued means that it does this by setting a flag somewhere, but not by keeping an exact record of how many signals have arrived.
      So if the signals is sent once, 5 times or more (try to press CTRL+C more times with your program: I have tried) while the signal handler is executing it produces the exactly same behaviour.



      In your second case you have 3 threads: the main one, t1, and t2: all of them are enabled to see the signal SIGINT and all of them have associated the same signal handler. If you press 3 times one after the other all three of them will execute the handler: that is why you don't see any delay. If you press very very fast though and more than 3 times (the number of threads listening to that signal) I think you will see something similar to the first behaviour.



      I will end my answer with the code I posted in a question where I was setting masks so that some signals were caught only by the main thread:



      int main()
      {
      int err;
      sigset_t omask, mask;
      pthread_t thread_motionSensor;
      pthread_t thread_tempReading;
      pthread_t thread_platformPost;

      printf("Created threads IDsn");

      ...
      if (signal(SIGINT, sig_handler)==SIG_ERR)
      printf("Error on recording SIGINT HANDLERn");

      /*Create a new mask to block all signals for the following thread*/
      sigfillset(&mask);
      pthread_sigmask(SIG_SETMASK, &mask, &omask);
      printf("Trying to create threadsn");
      if ((err = pthread_create (&thread_motionSensor, NULL, task1, NULL))!=0)
      {
      printf("Thread 1 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 1 created. Trying to create Thread 2n");
      if((err = pthread_create (&thread_tempReading, NULL, task2, NULL))!=0)
      {
      printf("Thread 2 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 2 created. Trying to create Thread 3n");
      if ((err = pthread_create (&thread_platformPost, NULL, task3, NULL))!=0)
      {
      printf("Thread 3 not created: error %d %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 3 createdn");
      /*The main thread must block the SIGALRM but catch SIGINT
      SIGQUIT, SIGTERM, SIgkILL*/
      /*empty the omask set from all signals */
      sigemptyset(&omask);
      /*add the signals to the omask*/
      sigaddset(&omask, SIGINT);
      sigaddset(&omask, SIGQUIT);
      sigaddset(&omask, SIGKILL);
      sigaddset(&omask, SIGTERM);
      /*unblock all signals in omask*/
      pthread_sigmask(SIG_UNBLOCK, &omask, NULL);
      printf("Main thread waiting for signaln");
      /*pause will stop the main thread until any signal not blocked by omask will be received*/
      pause();
      printf("Exit signal received: cancelling threadsn");

      pthread_cancel(thread_motionSensor);
      pthread_cancel(thread_tempReading);
      pthread_cancel(thread_platformPost);
      pthread_join(thread_motionSensor, NULL);
      pthread_join(thread_tempReading, NULL);
      pthread_join(thread_platformPost, NULL);
      printf("Exiting from main thread and processn");
      exit(0);
      }





      share|improve this answer


























      • +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

        – Louis Langholtz
        Dec 27 '18 at 15:04











      • Thanks... I will check them and see if I can improve it.

        – Francesco Boi
        Dec 27 '18 at 15:30
















      3














      INTRODUCTION



      First of all each thread has its own mask that specifies which signals it is listening to. When a thread is created it inherits the mask of the thread that is creating it (let me call it the parent thread) that is active when pthread_create is called.



      Generally it is better that if a thread is listening to a signal then the others should not, unless you want to have many threads that do the same stuff (for example when processing a connection request in a server to process many requests simultaneously). In this way you always know which thread is processing the signal. Otherwise you do not have any idea which thread is receiving the signal and which part of the program is executing: it becomes impossible to debug (an example is your own question).



      To change the mask of the child thread that is being created from the parent thread you create a new mask, you set it active, create a new thread with pthread_create and then in the parent thread set the previous mask active again (see the code at the end of the answer).



      EDIT: According to this post it is better to use sigaction() instead of signal. In modern systems signal() is implemented with sigaction() so there should not be any difference. However if its old implementation is used, problems might arise.



      ANSWER




      So signal only interrupt thread instead of the whole process if there
      are multi-threading?




      NO: Signals are just signals, they do not do anything. Actions associated to signals have the power to do stuff, including stopping the program or terminating the thread. Each signal has a default action associated and the default action for SIGINT is to interrupt the process.



      With you handler you are overwriting the default action. So it will not stop the program anymore but it will do what you have specified in the thread function.



      In the first case you have only one thread, the main one, which is an infinite loop, it always catch the signal as long as he is alive so that's why the behavior. If you resend the signal, the signal is momentarily blocked until the signal handler ends the execution. Nevertheless if many signals are sent while the handler is executing, you can loose some signals.
      In fact as explained here, blocked signals are set to pending, but not queued. The term pending means that the operating system remembers that there is a signal waiting to be delivered at the next opportunity by setting a flag, and not queued means that it does this by setting a flag somewhere, but not by keeping an exact record of how many signals have arrived.
      So if the signals is sent once, 5 times or more (try to press CTRL+C more times with your program: I have tried) while the signal handler is executing it produces the exactly same behaviour.



      In your second case you have 3 threads: the main one, t1, and t2: all of them are enabled to see the signal SIGINT and all of them have associated the same signal handler. If you press 3 times one after the other all three of them will execute the handler: that is why you don't see any delay. If you press very very fast though and more than 3 times (the number of threads listening to that signal) I think you will see something similar to the first behaviour.



      I will end my answer with the code I posted in a question where I was setting masks so that some signals were caught only by the main thread:



      int main()
      {
      int err;
      sigset_t omask, mask;
      pthread_t thread_motionSensor;
      pthread_t thread_tempReading;
      pthread_t thread_platformPost;

      printf("Created threads IDsn");

      ...
      if (signal(SIGINT, sig_handler)==SIG_ERR)
      printf("Error on recording SIGINT HANDLERn");

      /*Create a new mask to block all signals for the following thread*/
      sigfillset(&mask);
      pthread_sigmask(SIG_SETMASK, &mask, &omask);
      printf("Trying to create threadsn");
      if ((err = pthread_create (&thread_motionSensor, NULL, task1, NULL))!=0)
      {
      printf("Thread 1 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 1 created. Trying to create Thread 2n");
      if((err = pthread_create (&thread_tempReading, NULL, task2, NULL))!=0)
      {
      printf("Thread 2 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 2 created. Trying to create Thread 3n");
      if ((err = pthread_create (&thread_platformPost, NULL, task3, NULL))!=0)
      {
      printf("Thread 3 not created: error %d %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 3 createdn");
      /*The main thread must block the SIGALRM but catch SIGINT
      SIGQUIT, SIGTERM, SIgkILL*/
      /*empty the omask set from all signals */
      sigemptyset(&omask);
      /*add the signals to the omask*/
      sigaddset(&omask, SIGINT);
      sigaddset(&omask, SIGQUIT);
      sigaddset(&omask, SIGKILL);
      sigaddset(&omask, SIGTERM);
      /*unblock all signals in omask*/
      pthread_sigmask(SIG_UNBLOCK, &omask, NULL);
      printf("Main thread waiting for signaln");
      /*pause will stop the main thread until any signal not blocked by omask will be received*/
      pause();
      printf("Exit signal received: cancelling threadsn");

      pthread_cancel(thread_motionSensor);
      pthread_cancel(thread_tempReading);
      pthread_cancel(thread_platformPost);
      pthread_join(thread_motionSensor, NULL);
      pthread_join(thread_tempReading, NULL);
      pthread_join(thread_platformPost, NULL);
      printf("Exiting from main thread and processn");
      exit(0);
      }





      share|improve this answer


























      • +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

        – Louis Langholtz
        Dec 27 '18 at 15:04











      • Thanks... I will check them and see if I can improve it.

        – Francesco Boi
        Dec 27 '18 at 15:30














      3












      3








      3







      INTRODUCTION



      First of all each thread has its own mask that specifies which signals it is listening to. When a thread is created it inherits the mask of the thread that is creating it (let me call it the parent thread) that is active when pthread_create is called.



      Generally it is better that if a thread is listening to a signal then the others should not, unless you want to have many threads that do the same stuff (for example when processing a connection request in a server to process many requests simultaneously). In this way you always know which thread is processing the signal. Otherwise you do not have any idea which thread is receiving the signal and which part of the program is executing: it becomes impossible to debug (an example is your own question).



      To change the mask of the child thread that is being created from the parent thread you create a new mask, you set it active, create a new thread with pthread_create and then in the parent thread set the previous mask active again (see the code at the end of the answer).



      EDIT: According to this post it is better to use sigaction() instead of signal. In modern systems signal() is implemented with sigaction() so there should not be any difference. However if its old implementation is used, problems might arise.



      ANSWER




      So signal only interrupt thread instead of the whole process if there
      are multi-threading?




      NO: Signals are just signals, they do not do anything. Actions associated to signals have the power to do stuff, including stopping the program or terminating the thread. Each signal has a default action associated and the default action for SIGINT is to interrupt the process.



      With you handler you are overwriting the default action. So it will not stop the program anymore but it will do what you have specified in the thread function.



      In the first case you have only one thread, the main one, which is an infinite loop, it always catch the signal as long as he is alive so that's why the behavior. If you resend the signal, the signal is momentarily blocked until the signal handler ends the execution. Nevertheless if many signals are sent while the handler is executing, you can loose some signals.
      In fact as explained here, blocked signals are set to pending, but not queued. The term pending means that the operating system remembers that there is a signal waiting to be delivered at the next opportunity by setting a flag, and not queued means that it does this by setting a flag somewhere, but not by keeping an exact record of how many signals have arrived.
      So if the signals is sent once, 5 times or more (try to press CTRL+C more times with your program: I have tried) while the signal handler is executing it produces the exactly same behaviour.



      In your second case you have 3 threads: the main one, t1, and t2: all of them are enabled to see the signal SIGINT and all of them have associated the same signal handler. If you press 3 times one after the other all three of them will execute the handler: that is why you don't see any delay. If you press very very fast though and more than 3 times (the number of threads listening to that signal) I think you will see something similar to the first behaviour.



      I will end my answer with the code I posted in a question where I was setting masks so that some signals were caught only by the main thread:



      int main()
      {
      int err;
      sigset_t omask, mask;
      pthread_t thread_motionSensor;
      pthread_t thread_tempReading;
      pthread_t thread_platformPost;

      printf("Created threads IDsn");

      ...
      if (signal(SIGINT, sig_handler)==SIG_ERR)
      printf("Error on recording SIGINT HANDLERn");

      /*Create a new mask to block all signals for the following thread*/
      sigfillset(&mask);
      pthread_sigmask(SIG_SETMASK, &mask, &omask);
      printf("Trying to create threadsn");
      if ((err = pthread_create (&thread_motionSensor, NULL, task1, NULL))!=0)
      {
      printf("Thread 1 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 1 created. Trying to create Thread 2n");
      if((err = pthread_create (&thread_tempReading, NULL, task2, NULL))!=0)
      {
      printf("Thread 2 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 2 created. Trying to create Thread 3n");
      if ((err = pthread_create (&thread_platformPost, NULL, task3, NULL))!=0)
      {
      printf("Thread 3 not created: error %d %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 3 createdn");
      /*The main thread must block the SIGALRM but catch SIGINT
      SIGQUIT, SIGTERM, SIgkILL*/
      /*empty the omask set from all signals */
      sigemptyset(&omask);
      /*add the signals to the omask*/
      sigaddset(&omask, SIGINT);
      sigaddset(&omask, SIGQUIT);
      sigaddset(&omask, SIGKILL);
      sigaddset(&omask, SIGTERM);
      /*unblock all signals in omask*/
      pthread_sigmask(SIG_UNBLOCK, &omask, NULL);
      printf("Main thread waiting for signaln");
      /*pause will stop the main thread until any signal not blocked by omask will be received*/
      pause();
      printf("Exit signal received: cancelling threadsn");

      pthread_cancel(thread_motionSensor);
      pthread_cancel(thread_tempReading);
      pthread_cancel(thread_platformPost);
      pthread_join(thread_motionSensor, NULL);
      pthread_join(thread_tempReading, NULL);
      pthread_join(thread_platformPost, NULL);
      printf("Exiting from main thread and processn");
      exit(0);
      }





      share|improve this answer















      INTRODUCTION



      First of all each thread has its own mask that specifies which signals it is listening to. When a thread is created it inherits the mask of the thread that is creating it (let me call it the parent thread) that is active when pthread_create is called.



      Generally it is better that if a thread is listening to a signal then the others should not, unless you want to have many threads that do the same stuff (for example when processing a connection request in a server to process many requests simultaneously). In this way you always know which thread is processing the signal. Otherwise you do not have any idea which thread is receiving the signal and which part of the program is executing: it becomes impossible to debug (an example is your own question).



      To change the mask of the child thread that is being created from the parent thread you create a new mask, you set it active, create a new thread with pthread_create and then in the parent thread set the previous mask active again (see the code at the end of the answer).



      EDIT: According to this post it is better to use sigaction() instead of signal. In modern systems signal() is implemented with sigaction() so there should not be any difference. However if its old implementation is used, problems might arise.



      ANSWER




      So signal only interrupt thread instead of the whole process if there
      are multi-threading?




      NO: Signals are just signals, they do not do anything. Actions associated to signals have the power to do stuff, including stopping the program or terminating the thread. Each signal has a default action associated and the default action for SIGINT is to interrupt the process.



      With you handler you are overwriting the default action. So it will not stop the program anymore but it will do what you have specified in the thread function.



      In the first case you have only one thread, the main one, which is an infinite loop, it always catch the signal as long as he is alive so that's why the behavior. If you resend the signal, the signal is momentarily blocked until the signal handler ends the execution. Nevertheless if many signals are sent while the handler is executing, you can loose some signals.
      In fact as explained here, blocked signals are set to pending, but not queued. The term pending means that the operating system remembers that there is a signal waiting to be delivered at the next opportunity by setting a flag, and not queued means that it does this by setting a flag somewhere, but not by keeping an exact record of how many signals have arrived.
      So if the signals is sent once, 5 times or more (try to press CTRL+C more times with your program: I have tried) while the signal handler is executing it produces the exactly same behaviour.



      In your second case you have 3 threads: the main one, t1, and t2: all of them are enabled to see the signal SIGINT and all of them have associated the same signal handler. If you press 3 times one after the other all three of them will execute the handler: that is why you don't see any delay. If you press very very fast though and more than 3 times (the number of threads listening to that signal) I think you will see something similar to the first behaviour.



      I will end my answer with the code I posted in a question where I was setting masks so that some signals were caught only by the main thread:



      int main()
      {
      int err;
      sigset_t omask, mask;
      pthread_t thread_motionSensor;
      pthread_t thread_tempReading;
      pthread_t thread_platformPost;

      printf("Created threads IDsn");

      ...
      if (signal(SIGINT, sig_handler)==SIG_ERR)
      printf("Error on recording SIGINT HANDLERn");

      /*Create a new mask to block all signals for the following thread*/
      sigfillset(&mask);
      pthread_sigmask(SIG_SETMASK, &mask, &omask);
      printf("Trying to create threadsn");
      if ((err = pthread_create (&thread_motionSensor, NULL, task1, NULL))!=0)
      {
      printf("Thread 1 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 1 created. Trying to create Thread 2n");
      if((err = pthread_create (&thread_tempReading, NULL, task2, NULL))!=0)
      {
      printf("Thread 2 not created: error %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 2 created. Trying to create Thread 3n");
      if ((err = pthread_create (&thread_platformPost, NULL, task3, NULL))!=0)
      {
      printf("Thread 3 not created: error %d %dn", err);
      err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 3 createdn");
      /*The main thread must block the SIGALRM but catch SIGINT
      SIGQUIT, SIGTERM, SIgkILL*/
      /*empty the omask set from all signals */
      sigemptyset(&omask);
      /*add the signals to the omask*/
      sigaddset(&omask, SIGINT);
      sigaddset(&omask, SIGQUIT);
      sigaddset(&omask, SIGKILL);
      sigaddset(&omask, SIGTERM);
      /*unblock all signals in omask*/
      pthread_sigmask(SIG_UNBLOCK, &omask, NULL);
      printf("Main thread waiting for signaln");
      /*pause will stop the main thread until any signal not blocked by omask will be received*/
      pause();
      printf("Exit signal received: cancelling threadsn");

      pthread_cancel(thread_motionSensor);
      pthread_cancel(thread_tempReading);
      pthread_cancel(thread_platformPost);
      pthread_join(thread_motionSensor, NULL);
      pthread_join(thread_tempReading, NULL);
      pthread_join(thread_platformPost, NULL);
      printf("Exiting from main thread and processn");
      exit(0);
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 5 at 14:29

























      answered Dec 19 '18 at 12:33









      Francesco BoiFrancesco Boi

      2,60522543




      2,60522543













      • +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

        – Louis Langholtz
        Dec 27 '18 at 15:04











      • Thanks... I will check them and see if I can improve it.

        – Francesco Boi
        Dec 27 '18 at 15:30



















      • +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

        – Louis Langholtz
        Dec 27 '18 at 15:04











      • Thanks... I will check them and see if I can improve it.

        – Francesco Boi
        Dec 27 '18 at 15:30

















      +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

      – Louis Langholtz
      Dec 27 '18 at 15:04





      +1 on your answer. Here's a couple ideas for improvements: mentioning the async-signal-safe getpid(2) or pthread_self functions to get idea of thread handler is being invoked for; mentioning how Ctrl-C is typically handled by a shell, process groups, and the kill(2) function with negative PIDs.

      – Louis Langholtz
      Dec 27 '18 at 15:04













      Thanks... I will check them and see if I can improve it.

      – Francesco Boi
      Dec 27 '18 at 15:30





      Thanks... I will check them and see if I can improve it.

      – Francesco Boi
      Dec 27 '18 at 15:30













      1














      No matter how many threads the process has, some thread catches the signal and runs the signal handler while the other threads (if any) go on about their business. The signal is sent to the process, but what the process does when it gets the signal is dependent on how the process, and the threads in, configured its signal handlers.



      The full rules are quite complicated and I think it's safe to say that very few programmers bother to full understand them and generally avoid signals except for very limited purposes. See here for more details.






      share|improve this answer




























        1














        No matter how many threads the process has, some thread catches the signal and runs the signal handler while the other threads (if any) go on about their business. The signal is sent to the process, but what the process does when it gets the signal is dependent on how the process, and the threads in, configured its signal handlers.



        The full rules are quite complicated and I think it's safe to say that very few programmers bother to full understand them and generally avoid signals except for very limited purposes. See here for more details.






        share|improve this answer


























          1












          1








          1







          No matter how many threads the process has, some thread catches the signal and runs the signal handler while the other threads (if any) go on about their business. The signal is sent to the process, but what the process does when it gets the signal is dependent on how the process, and the threads in, configured its signal handlers.



          The full rules are quite complicated and I think it's safe to say that very few programmers bother to full understand them and generally avoid signals except for very limited purposes. See here for more details.






          share|improve this answer













          No matter how many threads the process has, some thread catches the signal and runs the signal handler while the other threads (if any) go on about their business. The signal is sent to the process, but what the process does when it gets the signal is dependent on how the process, and the threads in, configured its signal handlers.



          The full rules are quite complicated and I think it's safe to say that very few programmers bother to full understand them and generally avoid signals except for very limited purposes. See here for more details.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 19 '18 at 11:25









          David SchwartzDavid Schwartz

          138k14144226




          138k14144226























              1















              So signal only interrupt thread instead of the whole process if there are multi-threading?




              Yes. A signal interrupts a single thread of execution. At least according to the POSIX standard. C standard itself doesn't specify behaviour of processes or threads.



              If a signal is generated for a multi threaded process as opposed to being generated for particular thread, the signal will be delivered to exactly one of the threads belonging to that process (unless the signal is blocked by all threads).






              share|improve this answer






























                1















                So signal only interrupt thread instead of the whole process if there are multi-threading?




                Yes. A signal interrupts a single thread of execution. At least according to the POSIX standard. C standard itself doesn't specify behaviour of processes or threads.



                If a signal is generated for a multi threaded process as opposed to being generated for particular thread, the signal will be delivered to exactly one of the threads belonging to that process (unless the signal is blocked by all threads).






                share|improve this answer




























                  1












                  1








                  1








                  So signal only interrupt thread instead of the whole process if there are multi-threading?




                  Yes. A signal interrupts a single thread of execution. At least according to the POSIX standard. C standard itself doesn't specify behaviour of processes or threads.



                  If a signal is generated for a multi threaded process as opposed to being generated for particular thread, the signal will be delivered to exactly one of the threads belonging to that process (unless the signal is blocked by all threads).






                  share|improve this answer
















                  So signal only interrupt thread instead of the whole process if there are multi-threading?




                  Yes. A signal interrupts a single thread of execution. At least according to the POSIX standard. C standard itself doesn't specify behaviour of processes or threads.



                  If a signal is generated for a multi threaded process as opposed to being generated for particular thread, the signal will be delivered to exactly one of the threads belonging to that process (unless the signal is blocked by all threads).







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 19 '18 at 11:46

























                  answered Dec 19 '18 at 11:25









                  eerorikaeerorika

                  85.4k663132




                  85.4k663132






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53850202%2fsignal-handler-and-multithreading%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Mossoró

                      Can't read property showImagePicker of undefined in react native iOS

                      Pushsharp Apns notification error: 'InvalidToken'