Preserving the value of errno

S

Spiros Bousbouras

Assume I'm writing a function which is going to set
the value of errno if something went wrong but I also
want to guarantee that errno will remain unchanged
if the function completed its task succesfully. So at
the beginning of my code I have something like
int errsto = errno ;
and just before every successful return I have
errno = errsto ;

Is this ok ?
 
S

santosh

Spiros said:
Assume I'm writing a function which is going to set
the value of errno if something went wrong but I also
want to guarantee that errno will remain unchanged
if the function completed its task succesfully. So at
the beginning of my code I have something like
int errsto = errno ;
and just before every successful return I have
errno = errsto ;

Is this ok ?

You might want to volatile qualify your variable. Also library functions are
free to modify errno, even if not specified in the Standard. I don't think
it makes much sense to use errno for internal error documentation. A custom
mechanism might be much more robust and flexible and would not leave open
the chance for conflict with the system error mechanism.
 
P

Pietro Cerutti

Spiros said:
Assume I'm writing a function which is going to set
the value of errno if something went wrong but I also
want to guarantee that errno will remain unchanged
if the function completed its task succesfully. So at
the beginning of my code I have something like
int errsto = errno ;
and just before every successful return I have
errno = errsto ;

Is this ok ?

Why not just set errno to your error before returning when something
goes wrong?
 
M

Mark Bluemel

Pietro said:
Why not just set errno to your error before returning when something
goes wrong?
I assumed he wanted to guard against it being changed by any functions
he called in turn...
 
E

Eric Sosman

santosh wrote On 07/30/07 12:42,:
Spiros Bousbouras wrote:




You might want to volatile qualify your variable.

What for?
Also library functions are
free to modify errno, even if not specified in the Standard. I don't think
it makes much sense to use errno for internal error documentation. A custom
mechanism might be much more robust and flexible and would not leave open
the chance for conflict with the system error mechanism.

errno is a less-than-wonderful mechanism, agreed.
But occasionally it's useful to preserve an errno value
"just in case" it holds something that might be useful.
The O.P.'s use case doesn't make much sense to me (if
the caller cares about a pre-existing errno value, the
caller should grab it before calling other functions),
but a related case that *does* make sense is to preserve
errno while cleaning up from a failure inside a called
function:

int some_func(const char *name) {
FILE *stream;
char *fullpath = malloc(
strlen(directory) + 1 + strlen(name) + 1);
if (fullpath == NULL)
return NO_LUCK;
sprintf (fullpath, "%s/%s", directory, name);
stream = fopen(fullpath, "r");
if (stream == NULL) {
/* fopen may (only "may") have put useful
* data in errno, and we'd like to let our
* caller see it (if it's there). But we
* need to free fullpath before returning,
* and free might overwrite errno. So ...
*/
int errno_save = errno;
free (fullpath);
errno = errno_save;
return NO_LUCK;
}
...
fclose (stream);
free (fullpath);
return HOORAY;
}
 
A

Al Balmer

Assume I'm writing a function which is going to set
the value of errno if something went wrong but I also
want to guarantee that errno will remain unchanged
if the function completed its task succesfully. So at
the beginning of my code I have something like
int errsto = errno ;
and just before every successful return I have
errno = errsto ;

Is this ok ?

Sure. It's not something that's often useful, but I have written
library routines that did this. You might, for example, want to
capture an error return from another function, then return either that
or some other error depending on further processing.
 
P

Pietro Cerutti

Richard said:
Pietro Cerutti said:


Easily done, isn't it? <sigh> Ah well, tomorrow is another day.

Yes it is. What's the problem?

Sorry, I don't want to embark in off-topical debates, but what's wrong
with you?
 
R

Richard Heathfield

Pietro Cerutti said:
Sorry, I don't want to embark in off-topical debates, but what's wrong
with you?

I don't know. We all have our off-days, n'est-ce-pas? Well, I suppose
that today (actually, yesterday, as of four minutes ago) just happened
to be mine.
 
P

Pietro Cerutti

Richard said:
Pietro Cerutti said:


I don't know. We all have our off-days, n'est-ce-pas? Well, I suppose
that today (actually, yesterday, as of four minutes ago) just happened
to be mine.

No problem with that, best wishes for tomorrow (actually, today) ;-)
 
S

Spiros Bousbouras

errno is a less-than-wonderful mechanism, agreed.
But occasionally it's useful to preserve an errno value
"just in case" it holds something that might be useful.
The O.P.'s use case doesn't make much sense to me (if
the caller cares about a pre-existing errno value, the
caller should grab it before calling other functions)...

Indeed the caller could but I consider it The Right Thing
that a function which is going to use errno should only
modify it if something went wrong. I believe it makes
things overall more tidy. I actually believe that the
standard should specify that library functions should
only modify errno if something went wrong.

Consider the Unix specific readdir() For those not familiar
with it it returns successive directory entries on a Unix
system. You first open the directory with opendir() and
then you read the files by calling readdir() again and again.
readdir() will return a NULL pointer if it encounters an error
of if there are no more files to be read. So once readdir()
returns NULL the only way to tell if it was an error or the
end of the directory is to test the value of errno. This in
turns means that if you have a loop which is meant to read
all the directory entries then you have to set errno to 0
*every* time the loop gets repeated. On the other hand if it
was guaranteed that readdir() would only modify errno if
something went wrong and your loop only called readdir() then
you would only have to set errno to 0 once before entering
the loop.

This is as an example of why I feel that a function should
only modify errno if something went wrong. It's perhaps
a stylistic preference more than anything else but I do
prefer it.
 
E

Eric Sosman

Spiros said:
Indeed the caller could but I consider it The Right Thing
that a function which is going to use errno should only
modify it if something went wrong. I believe it makes
things overall more tidy. I actually believe that the
standard should specify that library functions should
only modify errno if something went wrong.

Consider the Unix specific readdir() For those not familiar
with it it returns successive directory entries on a Unix
system. You first open the directory with opendir() and
then you read the files by calling readdir() again and again.
readdir() will return a NULL pointer if it encounters an error
of if there are no more files to be read. So once readdir()
returns NULL the only way to tell if it was an error or the
end of the directory is to test the value of errno. This in
turns means that if you have a loop which is meant to read
all the directory entries then you have to set errno to 0
*every* time the loop gets repeated. On the other hand if it
was guaranteed that readdir() would only modify errno if
something went wrong and your loop only called readdir() then
you would only have to set errno to 0 once before entering
the loop.

Same amount of source code in either case, just
differently positioned. Nor is there likely to be any
gain in efficiency, because the fact that your `errno = 0;'
moves out of the loop is offset by the fact that readdir()
must now preserve and restore `errno' on every call.
This is as an example of why I feel that a function should
only modify errno if something went wrong. It's perhaps
a stylistic preference more than anything else but I do
prefer it.

Your preferences are your business, of course, but they
don't happen to be enforced by the Standard. Question 12.24
in the FAQ provides a pretty good hint about why this is so.
 
R

Richard Tobin

Eric Sosman said:
Nor is there likely to be any
gain in efficiency, because the fact that your `errno = 0;'
moves out of the loop is offset by the fact that readdir()
must now preserve and restore `errno' on every call.

Only if it does something that may change it when no error has
occurred.

-- Richard
 
S

Spiros Bousbouras

Same amount of source code in either case, just
differently positioned. Nor is there likely to be any
gain in efficiency, because the fact that your `errno = 0;'
moves out of the loop is offset by the fact that readdir()
must now preserve and restore `errno' on every call.

The positioning of code is important. I believe that annoying
little details should be dealt with at the lowest level possible
unless there are other (good) reasons to do otherwise and in
this case I don't feel there are. Nor is it necessary only a
matter of code positioning. If all the library functions
guaranteed that errno would only be modified in the case of an
error then many would not have to take any explicit measures
to preserve it. The exceptions would be functions in implementations
like those mentioned in FAQ 12.24 or functions which could do
their job in more than one ways and I feel these are a minority.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top