Problem
In errno.h, this variable is declared as extern int errno; so my question is, is it safe to check errno value after some calls or use perror() in multi-threaded code. Is this a thread safe variable? If not, then whats the alternative ?
On an x86 architecture, I’m running linux with gcc.
Asked by Vinit Dhatrak
Solution #1
It is thread safe, yes. The global errno variable on Linux is thread-specific. Errno must be threadsafe according to POSIX.
See http://www.unix.org/whitepapers/reentrant.html
Also see http://linux.die.net/man/3/errno
Answered by Charles Salvia
Solution #2
Errno is no longer a basic variable; it’s something more complicated behind the scenes, designed to be thread-safe.
$ man 3 errno errno errno errno errn
ERRNO(3) Linux Programmer’s Manual ERRNO(3)
NAME
errno - number of last error
SYNOPSIS
#include <errno.h>
DESCRIPTION
...
errno is defined by the ISO C standard to be a modifiable lvalue of
type int, and must not be explicitly declared; errno may be a macro.
errno is thread-local; setting it in one thread does not affect its
value in any other thread.
We can double-check:
$ cat > test.c
#include <errno.h>
f() { g(errno); }
$ cc -E test.c | grep ^f
f() { g((*__errno_location ())); }
$
Answered by DigitalRoss
Solution #3
The C standard states as follows:
errno is a macro that calls a function that returns the address of the current thread’s error number, then dereferences it.
Here’s what I have in /usr/include/bits/errno.h on Linux:
/* Function to get address of global `errno' variable. */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
# if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ())
# endif
Finally, it generates the following code:
> cat essai.c
#include <errno.h>
int
main(void)
{
errno = 0;
return 0;
}
> gcc -c -Wall -Wextra -pedantic essai.c
> objdump -d -M intel essai.o
essai.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 83 e4 f0 and esp,0xfffffff0
6: e8 fc ff ff ff call 7 <main+0x7> ; get address of errno in EAX
b: c7 00 00 00 00 00 mov DWORD PTR [eax],0x0 ; store 0 in errno
11: b8 00 00 00 00 mov eax,0x0
16: 89 ec mov esp,ebp
18: 5d pop ebp
19: c3 ret
Answered by Bastien Léonard
Solution #4
Yes, as the errno man page and other responses explain, errno is a thread local variable.
However, there is one minor aspect that could easily be overlooked. Any signal handler executing a system call should preserve and restore the errno. This is because the signal will be handled by one of the process threads which could overwrite its value.
As a result, signal handlers should preserve and restore the errno value. Something along these lines:
void sig_alarm(int signo)
{
int errno_save;
errno_save = errno;
//whatever with a system call
errno = errno_save;
}
Answered by marcmagransdeabril
Solution #5
On my Mac, this is from sys/errno.h:
#include <sys/cdefs.h>
__BEGIN_DECLS
extern int * __error(void);
#define errno (*__error())
__END_DECLS
So errno is now a function __error(). The function has been written in such a way that it is thread-safe.
Answered by vy32
Post is based on https://stackoverflow.com/questions/1694164/is-errno-thread-safe