Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check the value of errno?

I am using a system call and in case it fails, I need to do different things for different errnos.

I need to write code that looks something like this:

int res;
res = systemCall();
if (res == -1)
{
    if (errno == ENOMSG)
    {
        doSomething();
    }
    else
    {
        doSomethingElse();
    }
}

perror doesn't help, because it only prints the value.

As for strerro - if it is what I need, I am not suer how to use it, because here it says that the actual string is not the same as the error. Quote from the man page: "(For example, if errnum is EINVAL, the returned description will be "Invalid argument")".

I am using Linux. System calls: msgsend and msgrcv (https://linux.die.net/man/2/msgrcv). I am not sure what C libraries you are asking about.

I see I didn't explain myself well.

Is the statement if (errno == ENOMSG) valid? Is there such a variable errno? Basically my question is: What should go in the if statement in order to test the errno?

like image 720
Hana Avatar asked Sep 02 '17 11:09

Hana


People also ask

How do I check my errno value?

Viewing and Printing the Errno Value Your program can use the strerror() and perror() functions to print the value of errno. The strerror() function returns a pointer to an error message string that is associated with errno. The perror() function prints a message to stderr.

Where are errno values defined?

The <errno. h> header file defines the integer variable errno, which is set by system calls and some library functions in the event of an error to indicate what went wrong.

What is the default value of errno?

The initial value of errno at program startup is zero. In many cases, when a library function encounters an error, it will set errno to a non-zero value to indicate what specific error condition occurred.

What is errno variable?

The errno variable is an integer variable and set by system calls and library functions to indicate the source of an error.


1 Answers

How to check the value of errno:

  1. You will need to #include <errno.h>.
  2. Yes, you can definitely say things like if(errno == ENOENT) { ... }, and that is the common and recommended way of doing it.
  3. In general, do not use errno to determine that an error has occurred. Check the return value of the function, and if the return value indicates an error, then check errno to see what the error was. (More on this below.)
  4. errno looks like a variable, but it actually isn't. This doesn't concern you as long as you just say things like if(errno == ENOENT) { ... }. But you probably shouldn't try to do something like int errno_ptr = &errno;.
  5. You can use functions like perror() and strerror() to get human-readable error strings corresponding to errno values. But, yes, the strings you get are generally things like "No such file or directory". There is no good way that I know of to convert the errno value ENOENT to the string "ENOENT". (Addendum: see this question for some answers.)

To say a little more about #3. Sometimes it's tempting to say something like

errno = 0;
printf("Hello, world!\n");
if(errno != 0) {
    fprintf(stderr, "printf failed!\n");
}

But don't do that. Instead do

int retval = printf("Hello, world!\n");
if(retval < 0) {
    fprintf(stderr, "printf failed!\n");
}

The reason is that, somewhere in the process of doing its job, printf might have done something that resulted in an error, something that set errno, but printf might have recovered from that error and gone on to complete successfully.

There are a very few library functions that are guaranteed not to touch errno if there wasn't an error (I think one example might be atoi), but in general, this is something you have to be careful of.

To say a little more about #4. errno looks like a variable, and more specifically, it looks like a global variable. But of course global variables are bad. But errno has been around forever; there are tens of millions of lines of code that use it; it's still basically pretty convenient; it's too late to "fix" it. So, instead, if you peek behind the curtain, you'll find that most implementations do something like

extern int __errno_pointer;
#define errno (*__errno_pointer)

or

extern int *__errno_pointer_function();
#define errno (*__errno_function())

In this way, they can arrange for errno to work reasonably properly even in, say, multithreaded code.

like image 141
Steve Summit Avatar answered Oct 08 '22 00:10

Steve Summit