Coder Perfect

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 ?

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.


Also see

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)

       errno - number of last error

       #include <errno.h>


       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>

    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>
extern int * __error(void);
#define errno (*__error())

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