10.6 reentrant functions

Source: Internet
Author: User

When a signal is captured and started to be processed by the process, the sequence of instructions executed by the process is temporarily interrupted by the signal processing function, and the process immediately goes to the signal handler to begin execution if the signal processing function returns (rather than calling exit or LONGJMP, etc.). The sequence of instructions that the process is executing before entering the signal processing function is then executed, but in the signal processing function, we cannot know what happens when the process is executing that piece of code while the signal is being captured, if the process is using the function malloc to allocate additional memory on its heap. Or is the process in the process of invoking a function, for example, what will happen to Getpwnam? The function Getpwnam stores its results in a static area, which can cause a confusion, because malloc will usually save the allocated area to a list, and when the signal is captured, the process may be modifying the table, in the case of the function Getpwnam function, The results returned to the normal calling process may be overridden by the signal handler function.
The single UNIX specification details the functions that call security in the signal processing functions, which are reentrant and are called async-signal safe in a single UNIX specification. In addition to functions that can be re-entry functions, if it is detected in the process of the call can cause inconsistencies, the signal processing function calls to these functions will be blocked, figure 10.4 lists these async-signal safe functions, many of the functions are not reentrant because:

    1. The function uses a static data structure;
    2. The function calls the malloc or the free function;
    3. They are part of the standard IO function library.
      Many of the implementations of the standard IO libraries use global data structures in a non-reentrant manner, and note that in many of our cases, although we call the printf function in the signal processing function, we cannot guarantee that this will produce the desired effect. Because the signal processing function may interrupt the invocation of the printf function in the main program.

Note that is the signal processing function listed in Figure 10.4, there is only one errno variable for each thread, so we may inadvertently modify it unexpectedly. Assuming that the value of errno has just been set in main, an interrupt handler is called, and if the interrupt handler function calls the Read function, the call may change the value of the errno, overwriting the value just assigned in the main function, so a common rule is: When we call the functions listed in Figure 10.4 in the signal processing function, we should store and restore the errno, noting that a signal that is often captured is sigchld, and its signal processing function usually calls a wait function, All of the wait functions will change the value of errno.

Attention The function longjmp and the SIGLONGJMP function do not appear in Figure 10.4 because when the main program is updating the data structure in a non-reentrant way, the signal can occur, and if we call siglongjmp instead of returning in the signal handler, it may cause the data structure to be only updated by half, leaving The part can never be updated correctly. So if a function is dealing with something like updating a data structure, and the signal processing function can cause a call to the SIGSETJMP function, the application should block the signal when it updates the data structure.

Example

In the example in Figure 10.5, the non-reentrant function Getpwnamis called once per second in the Signal processing function:

  
 
  1. #include "apue.h"
  2. #include <pwd.h>
  3. static void my_alarm(int signo)
  4. {
  5. struct passwd *rootptr;
  6. printf("in signal handler\n");
  7. #if 1
  8. if((rootptr = getpwnam("root")) == NULL)
  9. {
  10. err_sys("getpwnam(root) error");
  11. }
  12. #endif
  13. printf("getpwnam function execute finish!\n");
  14. alarm(1);
  15. }
  16. int main(void)
  17. {
  18. struct passwd *ptr;
  19. signal(SIGALRM, my_alarm);
  20. alarm(1);
  21. while(1)
  22. {
  23. #if 1
  24. if((ptr = getpwnam("os")) == NULL)
  25. {
  26. err_sys("getpwnam error");
  27. }
  28. if(strcmp(ptr->pw_name, "os") != 0)
  29. {
  30. printf("return value correpted!, pw_name = %s\n", ptr->pw_name);
  31. }
  32. #endif
  33. }
  34. }
  35. "10_5.c" 76 lines, 633 characters

Compile the above program and test it on Debian, and when the above code is connected in # if 1, the effect is as follows:

 
   
  
  1. [email  protected] :~ /unixprogram/ chapter10$ ./ 10 _5 exe
  2. in signal handler
  3. ^ c
  4. [email protected] :~ /unixprogram/ chapter10$

The visible program is blocked when calling function Getpwnam within the signal processing function, and the program runs for a long time without seeing the output Getpwnam function execute finish!.
After a few changes to the above program can be seen, as long as one or two to #if 1 modify #if 0 , the program can follow its operation:

  
 
  1. [email protected]:~/UnixProgram/Chapter10$ ./10_5.exe
  2. in signal handler
  3. getpwnam function execute finish!
  4. in signal handler
  5. getpwnam function execute finish!
  6. in signal handler
  7. getpwnam function execute finish!
  8. in signal handler
  9. getpwnam function execute finish!
  10. in signal handler
  11. getpwnam function execute finish!
  12. ^C
  13. [email protected]:~/UnixProgram/Chapter10$

APUE.3E's explanation of the above procedure is described below:

When the above program runs, the results are random, usually, the program may be interrupted by the signal SIGSEGV(Invalid memory reference), the check of the core file shows that the main function has called the function Getpwnam, But when Getpwnam calls the function free, the timer signal handler interrupts it, and then calls the Getpwnam in the signal handler function, which calls the function again, usually in the signal ISGSEGV Run for a few seconds before the error is interrupted.

It can be seen that a non-reentrant function is called in a signal processing function, and the result is unpredictable.



From for notes (Wiz)

10.6 reentrant function

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.