Em errno.h
, essa variável é declarada como extern int errno;
minha pergunta é: é seguro verificar o errno
valor após algumas chamadas ou usar perror () no código multiencadeado. Essa é uma variável segura de thread? Se não, então qual é a alternativa?
Estou usando o linux com gcc na arquitetura x86.
c
linux
multithreading
gcc
Vinit Dhatrak
fonte
fonte
Respostas:
Sim, é seguro para threads. No Linux, a variável global errno é específica do segmento. O POSIX exige que o erro não seja seguro.
Veja http://www.unix.org/whitepapers/reentrant.html
Veja também http://linux.die.net/man/3/errno
fonte
# if !defined _LIBC || defined _LIBC_REENTRANT
_LIBC não está definido ao compilar programas normais. De qualquer forma, execute eco#include <errno.h>' | gcc -E -dM -xc -
e veja a diferença com e sem -pthread. errno é#define errno (*__errno_location ())
nos dois casos.sim
Errno não é mais uma variável simples, é algo complexo nos bastidores, especificamente para ser seguro para threads.
Veja
$ man 3 errno
:Podemos verificar:
fonte
Aqui está o que o padrão C diz:
Geralmente,
errno
é uma macro que chama uma função retornando o endereço do número do erro para o encadeamento atual e o desreferencia.Aqui está o que eu tenho no Linux, em /usr/include/bits/errno.h:
No final, ele gera esse tipo de código:
fonte
Em muitos sistemas Unix, a compilação com
-D_REENTRANT
garanteerrno
segurança de thread.Por exemplo:
fonte
-D_REENTRANT
. Consulte a discussão em outra resposta para a mesma pergunta.-D_XOPEN_SOURCE=500
ou-D_XOPEN_SOURCE=600
. Nem todo mundo se preocupa em garantir que o ambiente POSIX seja especificado - e então você-D_REENTRANT
pode salvar seu bacon. Mas você ainda precisa ter cuidado - em cada plataforma - para garantir o comportamento desejado.errno
que se expande para um lvalue modificável (201) que possuiint
duração de armazenamento local de tipo e encadeamento, cujo valor é definido como um número de erro positivo por várias funções da biblioteca. Se uma definição de macro for suprimida para acessar um objeto real ou um programa definir um identificador com o nomeerrno
, o comportamento será indefinido. [... continuação ...]errno
não precisa ser o identificador de um objeto. Pode expandir para um valor l modificável resultante de uma chamada de função (por exemplo,*errno()
). O texto principal continua: O valor de errno no encadeamento inicial é zero na inicialização do programa (o valor inicial de errno em outros encadeamentos é um valor indeterminado), mas nunca é definido como zero por nenhuma função da biblioteca. O POSIX usa o padrão C99 que não reconheceu threads. [... também continuou ...]Isto é do
<sys/errno.h>
meu Mac:Então
errno
agora é uma função__error()
. A função é implementada de modo a ser segura para threads.fonte
sim , como é explicado na página do manual errno e nas outras respostas, errno é uma variável local do encadeamento.
No entanto , há um detalhe bobo que pode ser facilmente esquecido. Os programas devem salvar e restaurar o erro em qualquer manipulador de sinal que esteja executando uma chamada do sistema. Isso ocorre porque o sinal será tratado por um dos threads do processo que pode sobrescrever seu valor.
Portanto, os manipuladores de sinal devem salvar e restaurar o erro. Algo como:
fonte
Eu acho que a resposta é "depende". As bibliotecas de tempo de execução C seguras para threads geralmente implementam errno como uma chamada de função (macro expandida para uma função) se você estiver criando código encadeado com os sinalizadores corretos.
fonte
Podemos verificar executando um programa simples em uma máquina.
Executando este programa e você pode ver endereços diferentes para errno em cada thread. A saída de uma execução na minha máquina parecia: -
Observe que o endereço é diferente para todos os segmentos.
fonte