En errno.h
, esta variable se declara extern int errno;
así , así que mi pregunta es, ¿es seguro verificar el errno
valor después de algunas llamadas o usar perror () en código de subprocesos múltiples? ¿Es esta una variable segura para subprocesos? Si no, ¿cuál es la alternativa?
Estoy usando Linux con gcc en la arquitectura x86.
c
linux
multithreading
gcc
vinit dhatrak
fuente
fuente
Respuestas:
Sí, es seguro para subprocesos. En Linux, la variable global errno es específica de subproceso. POSIX requiere que errno sea threadsafe.
Ver http://www.unix.org/whitepapers/reentrant.html
Ver también http://linux.die.net/man/3/errno
fuente
# if !defined _LIBC || defined _LIBC_REENTRANT
, _LIBC no está definido al compilar programas normales. De todos modos, ejecuta echo#include <errno.h>' | gcc -E -dM -xc -
y mira la diferencia con y sin hilo. errno es#define errno (*__errno_location ())
en ambos casos.si
Errno ya no es una variable simple, es algo complejo detrás de escena, específicamente para que sea seguro para subprocesos.
Ver
$ man 3 errno
:Podemos verificar dos veces:
fuente
Esto es lo que dice el estándar C:
En general,
errno
es una macro que llama a una función que devuelve la dirección del número de error para el subproceso actual y luego la desreferencia.Esto es lo que tengo en Linux, en /usr/include/bits/errno.h:
Al final, genera este tipo de código:
fuente
En muchos sistemas Unix, compilar con
-D_REENTRANT
garantiza queerrno
sea seguro para subprocesos.Por ejemplo:
fuente
-D_REENTRANT
. Consulte la discusión sobre otra respuesta para la misma pregunta.-D_XOPEN_SOURCE=500
o-D_XOPEN_SOURCE=600
. No todos se molestan en asegurarse de que se especifique el entorno POSIX, y luego-D_REENTRANT
pueden guardar su tocino. Pero aún debe tener cuidado, en cada plataforma, para asegurarse de obtener el comportamiento deseado.errno
que se expande a un valor l modificable (201) que tieneint
una duración de almacenamiento local de tipo e hilo, cuyo valor se establece en un número de error positivo por varias funciones de la biblioteca. Si se suprime una definición de macro para acceder a un objeto real, o un programa define un identificador con el nombreerrno
, el comportamiento es indefinido. [... continúa ...]errno
no necesita ser el identificador de un objeto. Puede expandirse a un valor l modificable como resultado de una llamada de función (por ejemplo,*errno()
). El texto principal continúa: el valor de errno en el subproceso inicial es cero al inicio del programa (el valor inicial de errno en otros subprocesos es un valor indeterminado), pero ninguna función de biblioteca establece nunca el valor en cero. POSIX usa el estándar C99 que no reconoció los hilos. [... también continuó ...]Esto es de
<sys/errno.h>
mi Mac:Entonces
errno
ahora es una función__error()
. La función se implementa para ser segura para subprocesos.fuente
sí , como se explica en la página del manual de errno y las otras respuestas, errno es una variable local de hilo.
Sin embargo , hay un detalle tonto que podría olvidarse fácilmente. Los programas deben guardar y restaurar el error en cualquier controlador de señal que ejecute una llamada al sistema. Esto se debe a que la señal será manejada por uno de los hilos del proceso que podría sobrescribir su valor.
Por lo tanto, los manejadores de señal deben guardar y restaurar errno. Algo como:
fuente
Creo que la respuesta es "depende". Las bibliotecas de tiempo de ejecución C seguras para subprocesos generalmente implementan errno como una llamada de función (macro que se expande a una función) si está creando código roscado con los indicadores correctos.
fuente
Podemos verificar ejecutando un programa simple en una máquina.
Al ejecutar este programa, puede ver diferentes direcciones para errno en cada hilo. El resultado de una ejecución en mi máquina se parecía a:
Tenga en cuenta que la dirección es diferente para todos los hilos.
fuente