Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is errno thread-safe?

People also ask

Is errno thread safe Windows?

Although MSVC is definitely not POSIX compliant, errno is implemented in the MSVC runtime (at least as of MSVC2008) in a threadsafe manner. Although the documentation states that it is extern int errno it's actually implemented as a #define to a function which allows thread-safety to be imposed.

Should you use errno?

The main reason for using errno is to give more information about the error condition. This is especially useful in situations where most (or even all) possible return values of a function are actually valid return values. Consider the fopen() function, which returns a pointer to a FILE .

What errno means?

It defines macros for reporting and retrieving error conditions using the symbol errno (short for "error number"). errno acts like an integer variable. A value (the error number) is stored in errno by certain library functions when they detect errors. At program startup, the value stored is zero.

Can I set errno?

To detect an error, an application must set errno to 0 before calling the function and check whether it is nonzero after the call. Affected functions include strcoll() , strxfrm() , strerror() , wcscoll() , wcsxfrm() , and fwide() . The C Standard allows these functions to set errno to a nonzero value on success.


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, errno is 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 same errno to be set. Under these circumstances, a thread might end up checking errno after it has already been updated by another thread.

To circumvent the resulting nondeterminism, POSIX.1c redefines errno as 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 symbol errno is defined by including the header , as specified by the C Standard ... For each thread of a process, the value of errno shall not be affected by function calls or assignments to errno by other threads.

Also see http://linux.die.net/man/3/errno

errno is thread-local; setting it in one thread does not affect its value in any other thread.


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 ())); }
$ 

In errno.h, this variable is declared as extern int errno;

Here is what the C standard says:

The macro errno need not be the identifier of an object. It might expand to a modifiable lvalue resulting from a function call (for example, *errno()).

Generally, errno is a macro which calls a function returning the address of the error number for the current thread, then dereferences it.

Here is what I have on Linux, in /usr/include/bits/errno.h:

/* 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

In the end, it generates this kind of 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

yes, as it is explained in the errno man page and the other replies, errno is a thread local variable.

However, there is a silly detail which could be easily forgotten. Programs should save and restore the errno on any signal handler executing a system call. This is because the signal will be handled by one of the process threads which could overwrite its value.

Therefore, the signal handlers should save and restore errno. Something like:

void sig_alarm(int signo)
{
 int errno_save;

 errno_save = errno;

 //whatever with a system call

 errno = errno_save;
}

This is from <sys/errno.h> on my Mac:

#include <sys/cdefs.h>
__BEGIN_DECLS
extern int * __error(void);
#define errno (*__error())
__END_DECLS

So errno is now a function __error(). The function is implemented so as to be thread-safe.


On many Unix systems, compiling with -D_REENTRANT ensures that errno is thread-safe.

For example:

#if defined(_REENTRANT) || _POSIX_C_SOURCE - 0 >= 199506L
extern int *___errno();
#define errno (*(___errno()))
#else
extern int errno;
/* ANSI C++ requires that errno be a macro */
#if __cplusplus >= 199711L
#define errno errno
#endif
#endif  /* defined(_REENTRANT) */