How to Invoke Non-reentrant Functions with Linux Signals?

A function is referred to as reentrant if it can be safely (and without side effects) invoked in the middle of its execution.

Some single-threaded applications can work with non-reentrant functions. Because most applications don’t handle signals or have recursive, callback functions at all. It would be challenging to debug the code if you load it to Linux Kernel as a module or in an embedded system.

Photo by Gabriel Heinzer on Unsplash

In this code, the function is a non-reentrant function. Because the function can be invoked immediately after the calculation is done (line number 7) and sets the value of the variable. It doesn't appear to be possible in this code, though. So, even with the non-reentrant function, this code is still viable.

Let’s run it:

Let’s handle a Linux Signal, SIGINT in the code:

Every time SIGINT (Ctrl + C) is sent to this code, the function will be invoked. Notice that the function creates a variable called

Let’s run it:

It seems to be working fine.

I will modify the function. The function modifies the global variable :

Let’s test it:

Since the variable is global, when the SIGINT signal is sent, the function modifies it. We represent I/O intensive function call in the function.

First, the function is called by the function (3 + 5). By the way, I sent a SIGINT signal to the program. The global variable has been changed. Therefore, we see the following line for a moment:

The problem is that the function is a non-reentrant function. We can fix the code like this:

It seems okay:

Sometimes, it is not possible to modify the reentrant functions. Because they are a part of glibc or a part of a third-party library. You may want to block the signal while executing the reentrant function and unblock the signal when you are done with the reentrant function:

Let’s run it:

We managed to fix the problem as it was a simple code. Imagine the compiler warns you when you try to modify a global variable.

Let’s try to write the same non-reentrant code in Rust:

Rust will force you to use global variables in the block. You can understand that something is suspicious here.

Why are malloc() and printf() non-reentrant functions?

https://stackoverflow.com/questions/3941271/why-are-malloc-and-printf-said-as-non-reentrant

Which functions can I use safely?

https://manpages.ubuntu.com/manpages/bionic/man7/signal-safety.7.html

P.S.: used to be a non-reentrant function. Therefore, was added to glibc. However, as of this commit, strtok is a wrapper for

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store