I see saying global variable update makes a function non-reentrant, this makes sense. But I do not understand why making local copy and restore can resolve it.
Here is an example:
int global_n = 10;
1 void foo()
2 {
3 int local_n = global_n;
4 global_n *= 10;
5 if (global_n < 100) {
6 printf("double digits\n");
7 } else {
8 printf("not double digits\n");
9 }
10 printf("%d\n", global_n);
11 global_n = local_n;
12 }
Let's say the first run of foo() executed line 4, now global_n is 100 and the run is interrupted by another run of foo(), and line 4 of this 2nd run made global_n 1000. So this function is still not reentrant.
Am I right?
Reference: Here is the quote from GNU libc got me asking the above question- if you want to call in a handler a function that modifies a particular object in memory, you can make this safe by saving and restoring that object.
I replaced "memory" with global variable.
CodePudding user response:
When they say
if you want to call in a handler a function that modifies a particular object in memory, you can make this safe by saving and restoring that object.
They mean you can write the signal handler so that its call to the function is safe by saving and restoring that object in the signal handler.
You cannot make a non-reentrant function reentrant by saving and restoring global variables or other shared state in the function. If the function modifies shared state, it is not reentrant.
Signal handlers should not call non-reentrant functions. But the signal handler itself does not need to be reentrant. The signal mask will (normally) prevent the signal handler from being re-entered. That is, unless the signal handler is assigned to multiple signals without masking other those other signals, or unless it removes its signal from the mask. And, of course, only one signal handler can play this game with a particular piece of shared state (unless you take care to ensure that all of the group of signal handlers which share that state are mutually masked).
So if the signal handler needs to call a function which modifies shared state, and it is known exactly what shared state is being modified, then that shared state could be saved in the signal handler before calling the non-reentrant function, and then restored in the signal handler after the non-reentrant function returns. This is all subject to the caveats at the end of the previous paragraph, and probably others.
Whether this is advisable is another question. I wouldn't advise it, personally. In fact, I would be inclined to fail a code review for a program which attempted it. There are just too many corner cases which need to be checked. But YMMV.