Dans errno.h
, cette variable est déclarée telle extern int errno;
que ma question est, est-il sûr de vérifier la errno
valeur après certains appels ou d'utiliser perror () dans du code multi-thread. Est-ce une variable thread-safe? Sinon, quelle est l'alternative?
J'utilise Linux avec gcc sur l'architecture x86.
c
linux
multithreading
gcc
vinit dhatrak
la source
la source
Réponses:
Oui, c'est thread-safe. Sous Linux, la variable globale errno est spécifique au thread. POSIX exige que errno soit threadsafe.
Voir http://www.unix.org/whitepapers/reentrant.html
Voir également http://linux.die.net/man/3/errno
la source
# if !defined _LIBC || defined _LIBC_REENTRANT
, _LIBC n'est pas défini lors de la compilation de programmes normaux. Quoi qu'il en soit, lancez echo#include <errno.h>' | gcc -E -dM -xc -
et regardez la différence avec et sans -pthread. errno est#define errno (*__errno_location ())
dans les deux cas.Oui
Errno n'est plus une simple variable, c'est quelque chose de complexe dans les coulisses, spécifiquement pour être thread-safe.
Voir
$ man 3 errno
:Nous pouvons vérifier:
la source
Voici ce que dit la norme C:
Généralement,
errno
est une macro qui appelle une fonction retournant l'adresse du numéro d'erreur pour le thread actuel, puis la déréférence.Voici ce que j'ai sur Linux, dans /usr/include/bits/errno.h:
Au final, il génère ce genre de code:
la source
Sur de nombreux systèmes Unix, la compilation avec
-D_REENTRANT
garantit laerrno
sécurité des threads.Par exemple:
la source
-D_REENTRANT
. Veuillez vous référer à la discussion sur une autre réponse pour la même question.-D_XOPEN_SOURCE=500
ou-D_XOPEN_SOURCE=600
. Tout le monde ne se soucie pas de s'assurer que l'environnement POSIX est spécifié - et-D_REENTRANT
peut ensuite sauver votre bacon. Mais il faut quand même faire attention - sur chaque plateforme - pour s'assurer d'obtenir le comportement souhaité.errno
qui se développe en une lvalue modifiable (201) qui aint
une durée de stockage locale de type et de thread, dont la valeur est définie sur un nombre d'erreur positif par plusieurs fonctions de bibliothèque. Si une définition de macro est supprimée pour accéder à un objet réel, ou si un programme définit un identifiant avec le nomerrno
, le comportement n'est pas défini. [... suite ...]errno
n'a pas besoin d'être l'identifiant d'un objet. Il peut s'étendre jusqu'à une lvalue modifiable résultant d'un appel de fonction (par exemple,*errno()
). Le texte principal continue: La valeur de errno dans le thread initial est zéro au démarrage du programme (la valeur initiale de errno dans les autres threads est une valeur indéterminée), mais n'est jamais mise à zéro par aucune fonction de bibliothèque. POSIX utilise le standard C99 qui ne reconnaissait pas les threads. [... également continué ...]C'est à partir
<sys/errno.h>
de mon Mac:Alors
errno
c'est maintenant une fonction__error()
. La fonction est implémentée de manière à être thread-safe.la source
oui , comme il est expliqué dans la page de manuel errno et les autres réponses, errno est une variable locale de thread.
Cependant , il y a un détail idiot qui pourrait être facilement oublié. Les programmes doivent enregistrer et restaurer le numéro d'erreur sur tout gestionnaire de signal exécutant un appel système. En effet, le signal sera traité par l'un des threads de processus qui pourrait écraser sa valeur.
Par conséquent, les gestionnaires de signaux doivent enregistrer et restaurer errno. Quelque chose comme:
la source
Je pense que la réponse est "ça dépend". Les bibliothèques d'exécution C thread-safe implémentent généralement errno en tant qu'appel de fonction (macro se développant en fonction) si vous créez du code thread avec les indicateurs appropriés.
la source
Nous pouvons vérifier en exécutant un programme simple sur une machine.
En exécutant ce programme, vous pouvez voir différentes adresses pour errno dans chaque thread. La sortie d'une course sur ma machine ressemblait à: -
Notez que l'adresse est différente pour tous les threads.
la source