Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

When to return EINVAL?

4,516 views
Skip to first unread message

Hallvard Breien Furuseth

unread,
Aug 5, 2013, 12:24:35 PM8/5/13
to
When should a library function return EINVAL (Invalid argument)? My
feeling is, it's only proper when it would have been trivial for the
user to predict the failure. But I don't know where I have that from.

This is for a C library whose functions return 0, a system errno, or
some negative private code. I know system errnos could be negative,
I think it was on BeOS, but I don't care until I meet such a beast.

I'm looking at some EINVALs which I think ought to be something
else. Transaction is now unusable, Arg > internal constant, etc.

--
Hallvard

Jorgen Grahn

unread,
Aug 5, 2013, 2:43:24 PM8/5/13
to
On Mon, 2013-08-05, Hallvard Breien Furuseth wrote:
> When should a library function return EINVAL (Invalid argument)? My
> feeling is, it's only proper when it would have been trivial for the
> user to predict the failure. But I don't know where I have that from.

I'm not sure it's more than a name and some ancient conventions.

I think I'd call EINVAL "Invalid argument due to programming error".
I.e. "if you had read the man page and followed it, this would not
have happened". (That doesn't mean all such errors end up as EINVAL;
EBADF and others belong in that category too).

> This is for a C library whose functions return 0, a system errno, or
> some negative private code. I know system errnos could be negative,
> I think it was on BeOS, but I don't care until I meet such a beast.
>
> I'm looking at some EINVALs which I think ought to be something
> else. Transaction is now unusable, Arg > internal constant, etc.

I don't know what "transaction is now unusable" means, but the second
one feels wrong. As a programmer you cannot avoid triggering that,
since the limit is undocumented.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

wil...@wilbur.25thandclement.com

unread,
Aug 5, 2013, 5:58:18 PM8/5/13
to
Hallvard Breien Furuseth <h.b.fu...@usit.uio.no> wrote:
> When should a library function return EINVAL (Invalid argument)? My
> feeling is, it's only proper when it would have been trivial for the
> user to predict the failure. But I don't know where I have that from.
>
> This is for a C library whose functions return 0, a system errno, or
> some negative private code. I know system errnos could be negative,
> I think it was on BeOS, but I don't care until I meet such a beast.

Both C99

"errno which expands to a modifiable lvalue that has type int, the
value of which is set to a positive error number by several library
functions." -- N1256 7.5p2

and POSIX

"The <errno.h> header shall define the following macros which shall
expand to integer constant expressions with type int, distinct
positive values" -- errno.h DSCRIPTION

"Values for errno are now required to be distinct positive values
rather than non-zero values. This change is for alignment with the
ISO/IEC 9899:1999 standard." -- errno.h CHANGE HISTORY Issue 6

mandate--more or less--that system errno values be positive. I suppose a
strict construction, particularly in the C99 case, allows for negative
values. But POSIX at least seems less equivocal, especially in the Issue 6
note.

Jens Thoms Toerring

unread,
Aug 5, 2013, 6:13:30 PM8/5/13
to
Hallvard Breien Furuseth <h.b.fu...@usit.uio.no> wrote:
> When should a library function return EINVAL (Invalid argument)? My
> feeling is, it's only proper when it would have been trivial for the
> user to predict the failure. But I don't know where I have that from.

> This is for a C library whose functions return 0, a system errno, or
> some negative private code. I know system errnos could be negative,
> I think it was on BeOS, but I don't care until I meet such a beast.

It's not really clear to me what you mean by "return". Do you
intend to have a return value of a function of EINVAL or do
you intend to set errno to EINVAL and return some value
from your functions that tells the user "something went
wrong and please have a look at 'errno' for the details"?

If you write your own library I'd consider "private" error
codes to be returned from functions to be the best method.
Values like EINVAL are, to me at least, associated with
'errno'. If you have error returns try to stay consistent
and either return a library specific error number (well
documented, of course;-) or return -1 on failure and set
'errno' (in which case every error should map unambiguous-
ly to the existing errno codes, so don't invent new ones -
macros starting with 'E' are actually reserved for the sys-
tem).

Don't start mixing them. What would be the use to a user of
flagging via a private code "some system error happend" with
errno being set to some value indicating why the system error
happened? The user won't know which system call failed and thus
the information from errno is rather useless for him or her (un-
less your library is a very thin layer on top of some system
calls and even a novice will have no problems figuring out
what probably happened under the hood). So better stay con-
sistent - have a set of error values returned that clearly in-
dicate what went wrong, so the user doesn't have to do guess-
work games.

> I'm looking at some EINVALs which I think ought to be something
> else. Transaction is now unusable, Arg > internal constant, etc.

I don't see it that way - EINVAL is something errno gets set
to. Don't mix that up with return values from your library.
Have an error like "MY_LIB_INVALID_ARGUMENT" as a return
value and don't "overload" what EINVAL means (i.e. the valued
of errno after a system call failed, returning -1 due to an
invalid function argument).
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

wil...@wilbur.25thandclement.com

unread,
Aug 5, 2013, 6:10:37 PM8/5/13
to
Hallvard Breien Furuseth <h.b.fu...@usit.uio.no> wrote:
> When should a library function return EINVAL (Invalid argument)? My
> feeling is, it's only proper when it would have been trivial for the
> user to predict the failure. But I don't know where I have that from.

Whatever it _should_ mean, in practice and outside of the C standard EINVAL
is a dumping ground. The line between static interface and runtime behavior
is often thin or non-existent, especially for non-trivial functions where
context matters. When in doubt even implementations tend to default to
EINVAL; this was a recent issue with Linux security policy hooks which
tended to break documented syscall behavior with unexpected EINVAL failures.

> This is for a C library whose functions return 0, a system errno, or
> some negative private code. I know system errnos could be negative,
> I think it was on BeOS, but I don't care until I meet such a beast.
>
> I'm looking at some EINVALs which I think ought to be something
> else. Transaction is now unusable, Arg > internal constant, etc.
>

I'd avoid using EINVAL for anything be. Fortunately, strerror(3) is
specified to handle any errno value, not just the ones defined by errno.h,
so there's no technical impediment to using your values even where
unsuspecting code doesn't use your error library. A confusing
strerror(-0xd0d0) message is hardly worse than a confusing strerror(EINVAL)
message, and in practice more useful because implementations tend to print
the unique value in decimal, which makes it easier to distinguish and
trackdown.

Scott Lurndal

unread,
Aug 5, 2013, 8:11:56 PM8/5/13
to
j...@toerring.de (Jens Thoms Toerring) writes:
>Hallvard Breien Furuseth <h.b.fu...@usit.uio.no> wrote:
>> When should a library function return EINVAL (Invalid argument)? My
>> feeling is, it's only proper when it would have been trivial for the
>> user to predict the failure. But I don't know where I have that from.
>
>> This is for a C library whose functions return 0, a system errno, or
>> some negative private code. I know system errnos could be negative,
>> I think it was on BeOS, but I don't care until I meet such a beast.
>
>It's not really clear to me what you mean by "return". Do you
>intend to have a return value of a function of EINVAL or do
>you intend to set errno to EINVAL and return some value
>from your functions that tells the user "something went
>wrong and please have a look at 'errno' for the details"?
>
>If you write your own library I'd consider "private" error
>codes to be returned from functions to be the best method.

Indeed, even Posix has left the return -1 and errno paradigm
behind, starting with the pthread_* interfaces which return
zero for success or the appropriate errno value for failure
(at the time they were added, errno wasn't yet thread safe).

scott

Richard Kettlewell

unread,
Aug 6, 2013, 3:18:56 AM8/6/13
to
AFAICS that only requires that the errors defined by C99 (resp. POSIX)
be positive, and doesn’t constrain any extensions an implementation may
add.

--
http://www.greenend.org.uk/rjk/

Jorgen Grahn

unread,
Aug 6, 2013, 4:35:29 AM8/6/13
to
On Mon, 2013-08-05, <wil...@wilbur.25thandClement.com> wrote:
> Hallvard Breien Furuseth <h.b.fu...@usit.uio.no> wrote:
>> When should a library function return EINVAL (Invalid argument)? My
>> feeling is, it's only proper when it would have been trivial for the
>> user to predict the failure. But I don't know where I have that from.
>
> Whatever it _should_ mean, in practice and outside of the C standard EINVAL
> is a dumping ground. The line between static interface and runtime behavior
> is often thin or non-existent, especially for non-trivial functions where
> context matters.

But in the traditional use with system calls, the context has to be
rather narrow and well-defined. IMHO the line should usually be
well-defined there.

> When in doubt even implementations tend to default to
> EINVAL; this was a recent issue with Linux security policy hooks which
> tended to break documented syscall behavior with unexpected EINVAL failures.

That seems like a clear bug. Your legacy software cannot know that
some new security policy is in place, so the error should be reported
as EPERM or something. Saying EINVAL is misleading.

Hallvard B Furuseth

unread,
Aug 6, 2013, 9:23:20 AM8/6/13
to
Thanks for the answers, folks. One clarification:

Jens Thoms Toerring writes:
>Hallvard Breien Furuseth <h.b.fu...@usit.uio.no> wrote:
>> When should a library function return EINVAL (Invalid argument)? My
>> feeling is, it's only proper when it would have been trivial for the
>> user to predict the failure. But I don't know where I have that from.
>
>> This is for a C library whose functions return 0, a system errno, or
>> some negative private code. I know system errnos could be negative,
>> I think it was on BeOS, but I don't care until I meet such a beast.
>
> It's not really clear to me what you mean by "return". Do you
> intend to have a return value of a function of EINVAL (...)

Yes. The library usually does "return errno;" after a syscall error.
It does not set errno. For other errors, it returns a code like EINVAL
or a private negative error code. That's too late to change at this
point, except it'd be feasible to never return errno.h values for
non-syscall errors. I don't see a problem with those though, since:

> If you write your own library I'd consider "private" error
> codes to be returned from functions to be the best method.
> Values like EINVAL are, to me at least, associated with
> 'errno'. (...)
> Don't start mixing them. What would be the use to a user of
> flagging via a private code "some system error happend" with
> errno being set to some value indicating why the system error
> happened? (...)

Doesn't happen. errno's value is irrelevant after a library call.

--
Hallvard

James K. Lowden

unread,
Aug 6, 2013, 8:39:45 PM8/6/13
to
On Tue, 06 Aug 2013 00:11:56 GMT
sc...@slp53.sl.home (Scott Lurndal) wrote:

> Indeed, even Posix has left the return -1 and errno paradigm
> behind, starting with the pthread_* interfaces which return
> zero for success or the appropriate errno value for failure

It's not clear that was a step forward, though. It breaks the simple
and useful paradigm

output = f(input);

which has served mathematics and programming pretty well.

Plauger remarks in his book on the C standard library that
error handling is messy, and suggests errno is probably OK
insofar as no clearly superior alternative has emerged.

--jkl

wil...@wilbur.25thandclement.com

unread,
Aug 7, 2013, 3:47:27 AM8/7/13
to
Richard Kettlewell <r...@greenend.org.uk> wrote:
> <wil...@wilbur.25thandClement.com> writes:
<snip>
>> mandate--more or less--that system errno values be positive. I suppose a
>> strict construction, particularly in the C99 case, allows for negative
>> values. But POSIX at least seems less equivocal, especially in the Issue 6
>> note.
>
> AFAICS that only requires that the errors defined by C99 (resp. POSIX)
> be positive, and doesn?t constrain any extensions an implementation may
> add.

What does "resp." mean? Is it a translated abbreviation from German as
Google suggests?

http://www.languagehat.com/archives/001173.php
http://forum.wordreference.com/showthread.php?t=2167934

BTW, I don't necessarily disagree with you. "Mandate" was too strong a word.
But normatively system errors appear to be always positive today. The POSIX
note clearly was wrong in its characterization of C99, but the impression
they took from the C standard was understandable. Perhaps it's a QoI
issue--extended negative system errors would be just really annoying.

Jorgen Grahn

unread,
Aug 7, 2013, 4:58:27 AM8/7/13
to
On Wed, 2013-08-07, James K. Lowden wrote:
> On Tue, 06 Aug 2013 00:11:56 GMT
> sc...@slp53.sl.home (Scott Lurndal) wrote:
>
>> Indeed, even Posix has left the return -1 and errno paradigm
>> behind, starting with the pthread_* interfaces which return
>> zero for success or the appropriate errno value for failure
>
> It's not clear that was a step forward, though. It breaks the simple
> and useful paradigm
>
> output = f(input);
>
> which has served mathematics and programming pretty well.

I suspect pthread_foo() usually has no output -- although
pthread_join() is a counterexample.

But yes, I too really prefer the value to be returned, rather than the
error. I often try to do something like this:

int err = 0;
const int foo = foobar(1, &err);
const int bar = foobar(2, &err);
const int baz = foobar(42, &err);
/* ... */
if(err) error_handling();

Richard Kettlewell

unread,
Aug 7, 2013, 5:04:59 AM8/7/13
to
<wil...@wilbur.25thandClement.com> writes:
> Richard Kettlewell <r...@greenend.org.uk> wrote:
>> <wil...@wilbur.25thandClement.com> writes:
> <snip>
>>> mandate--more or less--that system errno values be positive. I suppose a
>>> strict construction, particularly in the C99 case, allows for negative
>>> values. But POSIX at least seems less equivocal, especially in the Issue 6
>>> note.
>>
>> AFAICS that only requires that the errors defined by C99 (resp. POSIX)
>> be positive, and doesn?t constrain any extensions an implementation may
>> add.
>
> What does "resp." mean? Is it a translated abbreviation from German as
> Google suggests?

“respectively”. Nothing to do with German.

> BTW, I don't necessarily disagree with you. "Mandate" was too strong a word.
> But normatively system errors appear to be always positive today. The POSIX
> note clearly was wrong in its characterization of C99, but the impression
> they took from the C standard was understandable. Perhaps it's a QoI
> issue--extended negative system errors would be just really annoying.

That seems fair.

--
http://www.greenend.org.uk/rjk/

Nicolas George

unread,
Aug 7, 2013, 5:06:50 AM8/7/13
to
Jorgen Grahn , dans le message
<slrnl0431h.2...@frailea.sa.invalid>, a écrit :
> int err = 0;
> const int foo = foobar(1, &err);
> const int bar = foobar(2, &err);
> const int baz = foobar(42, &err);
> /* ... */
> if(err) error_handling();

if ((err = foobar(1, &foo)) ||
(err = foobar(2, &bar)) ||
(err = foobar(42 &baz)))
error_handling(err);

is not bad either. The output of a function is frequently more complex than
a single number or pointer, so returning it is not practical. And this code
snippet has the advantage on yours that it stops immediately on error.

OTOH, I am not very fond of a single integer as an error code: it is very
frequently not expressive enough.

Jorgen Grahn

unread,
Aug 7, 2013, 8:12:37 AM8/7/13
to
On Wed, 2013-08-07, Nicolas George wrote:
> Jorgen Grahn , dans le message
> <slrnl0431h.2...@frailea.sa.invalid>, a écrit :
>> int err = 0;
>> const int foo = foobar(1, &err);
>> const int bar = foobar(2, &err);
>> const int baz = foobar(42, &err);
>> /* ... */
>> if(err) error_handling();
>
> if ((err = foobar(1, &foo)) ||
> (err = foobar(2, &bar)) ||
> (err = foobar(42 &baz)))
> error_handling(err);
>
> is not bad either. The output of a function is frequently more complex than
> a single number or pointer, so returning it is not practical.

But returning structs has worked for ~30 years!

Still, I tend to use it for integers and things. One good thing about
returning a value is that you can let implicit type conversions do their
work. If foobar's value is a short, but I really want an int:

const int foo = foobar(1, &err);
if(err) error_handling();

versus

short tmp;
if(foobar(1, &tmp)) error_handling();
const int foo = tmp;

And more generally, you can use it in expressions:

foo += 3.14 * foobar(1, &err);

> And this code
> snippet has the advantage on yours that it stops immediately on error.

I implement foobar() so it does nothing if err is already non-zero.
It's less explicit than your version ... but if you think of it it's the
only sane interpretation: I couldn't get away with one single if(err)
... otherwise.

Nicolas George

unread,
Aug 7, 2013, 8:32:02 AM8/7/13
to
Jorgen Grahn , dans le message
<slrnl04edj.2...@frailea.sa.invalid>, a écrit :
> But returning structs has worked for ~30 years!

And it has been inefficient due to an extra copy for exactly the same time.

> And more generally, you can use it in expressions:
> foo += 3.14 * foobar(1, &err);

In my experience, there is usually a noticeable separation between functions
that return a value that you may want to use in an expression (for example
math functions and such) and functions that need to return an useful error
code (for example system calls and complex library utilities).

> I implement foobar() so it does nothing if err is already non-zero.

I do not know if I like this design.

> It's less explicit than your version ...

Depends on the reader, I find || very explicit. A frequent shell user will,
usually.

Jorgen Grahn

unread,
Aug 7, 2013, 10:18:22 AM8/7/13
to
On Wed, 2013-08-07, Nicolas George wrote:
> Jorgen Grahn , dans le message
> <slrnl04edj.2...@frailea.sa.invalid>, a écrit :
>> But returning structs has worked for ~30 years!
>
> And it has been inefficient due to an extra copy for exactly the same time.

Maybe, but I'm trying to learn to ignore efficiency when it doesn't
matter. I still find myself shaving microseconds off things that get
executed once a day ...

>> And more generally, you can use it in expressions:
>> foo += 3.14 * foobar(1, &err);
>
> In my experience, there is usually a noticeable separation between functions
> that return a value that you may want to use in an expression (for example
> math functions and such) and functions that need to return an useful error
> code (for example system calls and complex library utilities).
>
>> I implement foobar() so it does nothing if err is already non-zero.
>
> I do not know if I like this design.
>
>> It's less explicit than your version ...
>
> Depends on the reader, I find || very explicit. A frequent shell user will,
> usually.

Note that we're in agreement, not disagreement, about that part!

Richard Kettlewell

unread,
Aug 7, 2013, 11:42:15 AM8/7/13
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
> On Wed, 2013-08-07, Nicolas George wrote:
>> Jorgen Grahn , dans le message
>>> But returning structs has worked for ~30 years!
>> And it has been inefficient due to an extra copy for exactly the same time.
>
> Maybe, but I'm trying to learn to ignore efficiency when it doesn't
> matter. I still find myself shaving microseconds off things that get
> executed once a day ...

The curious thing is you get a copy even when it looks like it should be
unnecessary. (In GCC 4.7 on x86/amd64) the convention is to pass a
return pointer as a hidden first argument; the return value is stored
through this pointer. Yet code like this:

static struct foo x;
struct foo f();
...
x = f();

still allocates space on the stack (above the arguments) and passes a
pointer to that, then copies the result to x, when passing &x as the
return pointer would seem sufficient.

If there’s a good reason for this I’ve not yet got there...

--
http://www.greenend.org.uk/rjk/

Eric Sosman

unread,
Aug 7, 2013, 12:00:24 PM8/7/13
to
Flesh out your example a little:

struct foo f() {
struct foo result = x;
x.element += 42;
return result;
}

See the reason now?

--
Eric Sosman
eso...@comcast-dot-net.invalid

Eric Sosman

unread,
Aug 7, 2013, 12:02:15 PM8/7/13
to
Hmmm, no, wait, cancel that -- I don't see it, either.
Move along, nothing to see here.

--
Eric Sosman
eso...@comcast-dot-net.invalid
0 new messages