O funcție este denumită reintratoare dacă poate fi invocată în siguranță (și fără efecte secundare) în mijlocul execuției sale.

Unele aplicații cu un singur thread pot funcționa cu funcții care nu sunt reintrante. Deoarece majoritatea aplicațiilor nu gestionează semnale și nu au deloc funcții recursive de apel invers. Ar fi dificil să depanați codul dacă îl încărcați în Linux Kernel ca modul sau într-un sistem încorporat.

În acest cod, funcția calculate este o funcție care nu reintra. Deoarece funcția calculate poate fi invocată imediat după efectuarea calculului (linia numărul 7) și setează valoarea variabileisum. Totuși, nu pare să fie posibil în acest cod. Deci, chiar și cu funcția de non-reintrare, acest cod este încă viabil.

Hai să-l rulăm:

Să ne ocupăm de un semnal Linux, SIGINT în cod:

De fiecare dată când SIGINT (Ctrl + C) este trimis la acest cod, va fi invocată funcția signal_handler. Observați că funcția signal_handler creează o variabilă numită sum_internal

Hai să-l rulăm:

Se pare că funcționează bine.

Voi modifica funcția signal_handler. Funcția signal_handler modifică variabila globală sum :

Să-l testăm:

Deoarece variabila sum este globală, atunci când semnalul SIGINT este trimis, funcția signal_handler îl modifică. Reprezentăm apelul de funcție intensiv I/O în funcția calculate.

În primul rând, funcția calculate este apelată de funcția main (3 + 5). Apropo, am trimis un semnal SIGINT către program. Variabila globală sum a fost modificată. Prin urmare, vedem următoarea linie pentru un moment:

Result from main: 110

Problema este că funcția calculate este o funcție care nu reintra. Putem repara codul astfel:

Pare in regula:

Uneori, nu este posibilă modificarea funcțiilor de reintrare. Pentru că fac parte din glibc sau dintr-o bibliotecă terță parte. Poate doriți să blocați semnalul în timp ce executați funcția de reintrare și să deblocați semnalul când ați terminat cu funcția de reintrare:

Hai să-l rulăm:

Am reușit să remediam problema deoarece era un cod simplu. Imaginați-vă că compilatorul vă avertizează când încercați să modificați o variabilă globală.

Să încercăm să scriem același cod non-reintrat în Rust:

Rust vă va forța să utilizați variabile globale în blocul unsafe. Puteți înțelege că ceva este suspect aici.

De ce funcțiile malloc() și printf() sunt nereintrante?

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

Ce funcții pot folosi în siguranță?

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

P.S.: strtok era o funcție care nu reintra. Prin urmare, strtok_r a fost adăugat la glibc. Cu toate acestea, „începând cu acest commit”, strtok este un wrapper pentru strtok_r