How to avoid using printf in a signal handler?

后端 未结 7 953
青春惊慌失措
青春惊慌失措 2020-11-21 06:35

Since printf is not reentrant, it\'s not supposed to be safe to use it in a signal handler. But I\'ve seen lots of example codes that uses printf t

相关标签:
7条回答
  • 2020-11-21 07:03

    You can use some flag variable, set that flag inside signal handler, and based on that flag call printf() function in main() or other part of program during normal operation.

    It is not safe to call all functions, such as printf, from within a signal handler. A useful technique is to use a signal handler to set a flag and then check that flag from the main program and print a message if required.

    Notice in example below, signal handler ding() set a flag alarm_fired to 1 as SIGALRM caught and in main function alarm_fired value is examined to conditionally call printf correctly.

    static int alarm_fired = 0;
    void ding(int sig) // can be called asynchronously
    {
      alarm_fired = 1; // set flag
    }
    int main()
    {
        pid_t pid;
        printf("alarm application starting\n");
        pid = fork();
        switch(pid) {
            case -1:
                /* Failure */
                perror("fork failed");
                exit(1);
            case 0:
                /* child */
                sleep(5);
                kill(getppid(), SIGALRM);
                exit(0);
        }
        /* if we get here we are the parent process */
        printf("waiting for alarm to go off\n");
        (void) signal(SIGALRM, ding);
        pause();
        if (alarm_fired)  // check flag to call printf
          printf("Ding!\n");
        printf("done\n");
        exit(0);
    }
    

    Reference: Beginning Linux Programming, 4th Edition, In this book exactly your code is explained (what you want), Chapter 11: Processes and Signals, page 484

    Additionally, you need to take special care in writing handler functions because they can be called asynchronously. That is, a handler might be called at any point in the program, unpredictably. If two signals arrive during a very short interval, one handler can run within another. And It is considered better practice to declare volatile sigatomic_t, this type are always accessed atomically, avoid uncertainty about interrupting access to a variable. (read: Atomic Data Access and Signal Handling for detail expiation).

    Read Defining Signal Handlers :to learn how to write a signal handler function that can be established with the signal() or sigaction() functions.
    List of authorized functions in manual page, calling this function inside signal handler is safe.

    0 讨论(0)
提交回复
热议问题