Is errno thread local?
stackoverflow Is errno thread-safe?
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 ?
I am using linux with gcc on x86 architecture.
A
Yes, it is thread safe. On Linux, the global errno variable is thread-specific. POSIX requires that errno be threadsafe.
See http://www.unix.org/whitepapers/reentrant.html
In POSIX.1,
errnois defined as an external global variable. But this definition is unacceptable in a multithreaded environment, because its use can result in nondeterministic results. The problem is that two or more threads can encounter errors, all causing the sameerrnoto be set. Under these circumstances, a thread might end up checkingerrnoafter it has already been updated by another thread.To circumvent the resulting nondeterminism, POSIX.1c redefines
errnoas a service that can access the per-thread error number as follows (ISO/IEC 9945:1-1996, §2.4):Some functions may provide the error number in a variable accessed through the symbol
errno. The symbolerrnois defined by including the header , as specified by the C Standard ... For each thread of a process, the value oferrnoshall not be affected by function calls or assignments to errno by other threads.
Also see http://linux.die.net/man/3/errno
errnois thread-local; setting it in one thread does not affect its value in any other thread.
A
Yes
Errno isn't a simple variable anymore, it's something complex behind the scenes, specifically for it to be thread-safe.
See $ man 3 errno:
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 ())); }
$