Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: updated for C11

...

Note that this code first sets errno to 0 to comply with ERR30-C. Set errno to zero before calling a library function known to set errno, and check errno only after the function returns a value indicating failure.

Compliant Solution

Noncompliant Code Example (strerror_s(), C99)

This noncompliant code example The compliant solution uses the POSIX strerror_r() function, which has the same functionality as strerror() but guarantees thread safety.

Code Block
bgColor#FFCCCC
langc
errno = 0;
FILE* fd = fopen( filename, "r");
if (fd == NULL) {
  char errmsg[BUFSIZ];
  if (strerror_r(errno, errmsg, BUFSIZ) != 0) {
    /* handle error */
  }
  printf("Could not open file because of %s\n", errmsg);
}

While this code prevents a race window from being exploited within the strerror_r() function itself, the fact that errno is a static variable means there is still a race window between the fopen() call and the beginning of the strerror_r() call, in which another thread could modify errno.

Compliant Solution (Mutex, pthreads) 

This compliant solution adds a mutex to protect the access of errno by multiple threads.

Code Block
bgColor#ccccff
langc
static pthread_mutex_t errno_mutex;
int result;
if ((result = pthread_mutex_lock(&errno_mutex)) == 0) {
  /* Handle error */
}
errno = 0;
FILE* fd = fopen( filename, "r");
if (fd == NULL) {
  char errmsg[BUFSIZ];
  if (strerror_r(errno, errmsg, BUFSIZ) != 0) {
    /* handle error */
  }
  printf("Could not open file because of %s\n", errmsg);
}
if ((result = pthread_mutex_unlock(&errno_mutex)) == 0) {
  /* Handle error */
}

Note that Linux provides two versions of strerror_r(), known as the XSI-compliant version and the GNU-specific version. This compliant solution assumes the XSI-compliant version. You can get the XSI-compliant version if you compile applications in the way POSIX requires (that is, by defining _POSIX_C_SOURCE or _XOPEN_SOURCE appropriately). Check your strerror_r() manual page to see which version(s) are available on your system.

Compliant Solution (strerror_s(), C11

...