Thread: Permute signal handlers

  1. #1
    Registered User
    Join Date
    Apr 2020
    Posts
    24

    Permute signal handlers

    Hello everyone,

    I am trying to write a program that includes signals handling.
    My program should not stop when he receives a SIGINT signal, he should printf a message instead.
    This message should change at every single time my program receives a SIGQUIT signal.
    So my program prints "message number 1" at the first reception of a SIGINT signal. then, if he receives a SIGQUIT signal, then the next time he receives a SIGINT signal, that's "message number 2" who should be displayed...

    I am trying to do this using *sig_before, it seems quite logical.
    However I am not sure that I should use three handlers like shown in the code.

    Can someone get me some help here ?

    thanks in advance
    Code:
    #include <signal.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <string.h>
    #include <unistd.h>
    
    #define True 1
    
    void (*sig_before)(int); /* to use for permutation */
    
    void work() {
      while(True){
        sleep(100000);
      }
    }
    
    void work() __attribute__((noreturn));
    
    /* signal handlers */
    void sighdl1(int n) {
      printf("message number 1 \n");
    }
    void sighdl2(int n) {
      printf("message number 2 \n");
    }
    void quithdlr(int n) {
      printf("signal %i received, messages permutation", n);
    } 
    
    /* the main of my program*/
    int main() {
    /* here I would like to use the call system signal and sig_before so that my program can swap from one signal handler to another when he receives a QUIT signal */
      signal(SIGINT, sighdl1);
      work();
    
    }

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    You need to be careful what you do in a signal handler. It's best that they do as little as possible. In particular, functions like printf are generally not supposed to be used inside them. signal-safety(7) - Linux manual page

    Instead of defining your own True, just use <stdbool.h> which defines true, false, and bool.

    You'll need to kill the program from another terminal:
    Code:
    $ ps -C a.out
      PID TTY          TIME CMD
    10374 pts/0    00:00:00 a.out
    $ kill -s USR1 10374
    Keys:
    SIGINT: ctrl+C
    SIGQUIT: ctrl+\ (or maybe ctrl+Y)
    Code:
    #include <signal.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
     
    #include <sys/types.h>
    #include <unistd.h>
     
    #define NumMessages 2
     
    sig_atomic_t g_msg_num = -1;
    sig_atomic_t g_cur_msg_num = 0;
     
    void work() {
        static const char *msgs[] = {
            "message 1",
            "message 2"
        };
        while (true) {
            sleep(1); // one second is enough
            if (g_msg_num != -1) {
                printf("%s\n", msgs[g_msg_num]);
                g_msg_num = -1;
            }
        }
    }
     
    void inthdlr(int n) {
        g_msg_num = g_cur_msg_num;
        signal(SIGINT, inthdlr);
    }
     
    void quithdlr(int n) {
        g_cur_msg_num = (g_cur_msg_num + 1) % NumMessages;
        signal(SIGQUIT, quithdlr);
    }
     
    int main() {
        signal(SIGINT, inthdlr);
        signal(SIGQUIT, quithdlr);
        work();
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    And... avoid to use signal()... it is outdated.
    Use sigaction().

  4. #4
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    Quote Originally Posted by flp1969 View Post
    And... avoid to use signal()... it is outdated.
    Use sigaction().
    that is noted, thank u for the advice

  5. #5
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    Quote Originally Posted by john.c View Post
    You need to be careful what you do in a signal handler. It's best that they do as little as possible. In particular, functions like printf are generally not supposed to be used inside them. signal-safety(7) - Linux manual page

    Instead of defining your own True, just use <stdbool.h> which defines true, false, and bool.

    You'll need to kill the program from another terminal:
    Code:
    $ ps -C a.out
      PID TTY          TIME CMD
    10374 pts/0    00:00:00 a.out
    $ kill -s USR1 10374
    Keys:
    SIGINT: ctrl+C
    SIGQUIT: ctrl+\ (or maybe ctrl+Y)
    Code:
    #include <signal.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
     
    #include <sys/types.h>
    #include <unistd.h>
     
    #define NumMessages 2
     
    sig_atomic_t g_msg_num = -1;
    sig_atomic_t g_cur_msg_num = 0;
     
    void work() {
        static const char *msgs[] = {
            "message 1",
            "message 2"
        };
        while (true) {
            sleep(1); // one second is enough
            if (g_msg_num != -1) {
                printf("%s\n", msgs[g_msg_num]);
                g_msg_num = -1;
            }
        }
    }
     
    void inthdlr(int n) {
        g_msg_num = g_cur_msg_num;
        signal(SIGINT, inthdlr);
    }
     
    void quithdlr(int n) {
        g_cur_msg_num = (g_cur_msg_num + 1) % NumMessages;
        signal(SIGQUIT, quithdlr);
    }
     
    int main() {
        signal(SIGINT, inthdlr);
        signal(SIGQUIT, quithdlr);
        work();
    }
    Thank u John for ur reply, it was very helpful !! However, in this program, I would like to use the fact that signal() call system returns a pointer to the last signal handler used to handle the same type of signal (which is SIGINT in our case). That is why I used void (*sig_before)(int); in the beginning.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You can do the same with sigaction.
    Code:
           int sigaction(int signum, const struct sigaction *act,
                         struct sigaction *oldact);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    @Ramsis94, get the GNU C Library manual and take a look at printf() funcion at 12.12.7 (page 277):

    Permute signal handlers-untitled-jpg

    Notice the "AS-Unsafe" at "Preliminary". This means, printf() isn't safe to use in signal handlers (Async-Signal safety).
    The definition of these terms are in 1.2.2.1 - "POSIX Safety Concepts".

    As @john.c told you, printf() isn't signal safe.

    You may ask: "How can I print a simple string in stdout, then?". Using write() function (which is AS-Safe):

    Code:
    static const char str[] = "hello";
    ...
    write( STDOUT_FILENO, str, sizeof str - 1 );
    Last edited by flp1969; 04-22-2020 at 12:51 PM.

  8. #8
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    I see, thanks a lot

  9. #9
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    Quote Originally Posted by Salem View Post
    You can do the same with sigaction.
    Code:
           int sigaction(int signum, const struct sigaction *act,
                         struct sigaction *oldact);
    Apparently yes, but I am not familiar with sigaction() and I don't know how to use it

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Apparently yes, but I am not familiar with sigaction() and I don't know how to use it
    And?

    Presumably there were previous times when you didn't know what signal() was, or what printf() was, and that didn't stop you.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Apr 2020
    Posts
    24
    Quote Originally Posted by Salem View Post
    > Apparently yes, but I am not familiar with sigaction() and I don't know how to use it
    And?

    Presumably there were previous times when you didn't know what signal() was, or what printf() was, and that didn't stop you.
    You are right ! I am learning too much new things these days

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. TSP - C - Can't permute and add correctly.
    By ronogon in forum C Programming
    Replies: 5
    Last Post: 03-09-2013, 01:35 AM
  2. When to re-enable signal handlers
    By kr0n1x in forum Linux Programming
    Replies: 4
    Last Post: 08-18-2012, 04:18 PM
  3. GTK+ C++ compiler and signal handlers
    By nickstyle in forum C++ Programming
    Replies: 6
    Last Post: 03-19-2012, 06:45 AM
  4. Return Handlers
    By Laks in forum C Programming
    Replies: 0
    Last Post: 11-22-2009, 07:18 AM
  5. Signal Handlers
    By MethodMan in forum Linux Programming
    Replies: 1
    Last Post: 03-05-2003, 12:20 AM

Tags for this Thread