[mod.std.unix] Does EFAULT still make sense as an error return?

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/09/85)

Date: 06 Oct 85 18:54:15 +1000 (Sun)
>From: Robert Elz <munnari!kre@seismo.CSS.GOV>

I notice that P1003 has gone to a lot of trouble (I refer to draft 4)
to specift that EFAULT is a possible error return from every system
call that takes a pointer as one of its arguments (or if there are
any that were missed, I missed them too!)

I have yet to see an implementation that will actually return EFAULT
in many of those instances - consider "time()", "wait()", and "pipe()".

[ System V Release 2 claims to return EFAULT in most of these
cases, including time() and wait().  (I don't know if it really
does.)  Clearly this is what one would want to have happen.
If a signal occurred instead, and the user signal catcher
returned normally, how would one then complete the system
call?  Surely not by returning EINTR :-)  -Gwyn ]

In each of those, the system call definition specifies that a pointer
to a data structure of one type or another is an argument.  However,
all implementatins that I am aware of do not actually pass the pointer
across the user/kernel interface, preferring rather the obtain the
returned value via some system defined internal mechanism, and have the
user interface routine actually store it in the data structure the
user intended.

If such an implementation is required to return EFAULT rather than
send a signal to the process, much extra work is going to be involved.
Since (probably) all implementations are involved here, it seems to
me that things should be relaxed here.

[ Agreed.  -Kretsch ]

[ Isn't u.u_error available for the copyout() code?  Setting it
to EFAULT instead of posting a signal seems a trivial change.  -Gwyn ]

I would add the following sentence to the definition of EFAULT in
section 2.3 [ of Draft 4; Section 2.4 of Draft 5 -jsq ]:

	This condition may generate a signal; the error is returned
	if the signal is not generated, or is ignored.

[ I'm not sure this is the proper action.  This may cause currently
working programs to break.  -Kretsch ]

This closely follows the wording of the similar condition with EPIPE,
except that it allows implementations to decide in which cases they
will send a signal, and in which cases they will return EFAULT.

[ This may turn out to be a good compromise solution.  -Gwyn ]

I would actually prefer if new kernel implementations could dispense
with EFAULT entirely, and send a SIGSEGV instead (returning EFAULT
only if the signal is ignored).

This would greatly help to blur the distinction between what is
a "system call" and what is a "library routine".

It seems to me, that now the time has come when most of us no longer
write code in assembler, this distinction is outdated.  To me,
a "system call" and a "library routine" look just the same.

If the kernel sent a signal whenever it detected an illegal address
in an argument provided by a user to a system call, then system
calls would behave just like library routines, and it would be
much easier for an implementation to choose how to implement
any particular function.  For example, on some systems, it may
be desirable to implement "uname()" as a library routine that reads
a file - to allow the data returned to be easily changed by
the site administrators.  This is not going to be easy to do
if uname() is constrained to return EFAULT and not send a SIGSEGV.

[ Indeed, one of the silliest parts of emulating system calls
with library routines (as in my System V emulation for 4.2BSD)
is the attempt to return EFAULT instead of causing a SIGSEGV.

What you say is quite right, but it would be a significant change
from the System V baseline so I suspect we would not arrive at a
consensus in favor of the SIGSEGV approach.

Draft 5 Appendix A.7 specifically mentions problems with EFAULT
and solicits suggestions for incorporation into the "final use"
standard.  -Gwyn ]

Robert Elz		seismo!munnari!kre   kre%munnari.oz@seismo.css.gov

Volume-Number: Volume 3, Number 9

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/14/85)

Date: Sun, 10 Nov 85 16:19:03 PST
From: mordor!lll-crg!sun!guy (Guy Harris)

> [ System V Release 2 claims to return EFAULT in most of these
> cases, including time() and wait().  (I don't know if it really
> does.)  Clearly this is what one would want to have happen.
> If a signal occurred instead, and the user signal catcher
> returned normally, how would one then complete the system
> call?  Surely not by returning EINTR :-)  -Gwyn ]

Normally, one wouldn't *want* to complete the system call in this case; how
do you complete a call to "time" where the pointer points into some
nonexistent or non-writable location?  The only case where this would be
useful is in something like (aargh) the Bourne shell, where the signal
catcher would grow the data space to make that pointer valid.  This would
only work with 4.xBSD-style restartable system calls; the system call should
*not* be completed, but re-executed.

> [ Isn't u.u_error available for the copyout() code?  Setting it
> to EFAULT instead of posting a signal seems a trivial change.  -Gwyn ]

"copyout" isn't being used here; the copying of the data from the registers
it's usually returned in (for calls like "wait", "time", and "pipe") into
the location pointed to by the argument to the system call is done by
user-mode code, and it'd have to catch SIGSEGV in order to make the system
call return EFAULT in that particular case (oh yes, and in the cases of
"wait" and "pipe", you couldn't re-execute the call).

> I would add the following sentence to the definition of EFAULT in
> section 2.3 [ of Draft 4; Section 2.4 of Draft 5 -jsq ]:

> 	This condition may generate a signal; the error is returned
> 	if the signal is not generated, or is ignored.

> [ I'm not sure this is the proper action.  This may cause currently
> working programs to break.  -Kretsch ]

1) The P1003 standard *already* breaks currently working programs; no UNIX
which is currently available returns -1 and sets "errno" to EAGAIN on
no-delay reads or writes - either it returns 0 (S3, S5) or returns -1 and
sets "errno" to EWOULDBLOCK.

2) It's not clear that *reasonable* existing programs would be broken - what
can you do with an EFAULT except print an error message and exit?  Getting a
SIGSEGV would do both of the above, at least with a reasonable parent
process (like a shell), and would have the added advantage of giving you a
core dump so you can debug the problem more easily (if a system call gets
EFAULT, there is buggy code somewhere).

> I would actually prefer if new kernel implementations could dispense
> with EFAULT entirely, and send a SIGSEGV instead (returning EFAULT
> only if the signal is ignored).

YES.  V6 (!) did this; EFAULT was added subsequent to the release of V6, and
appeared in PWB/UNIX 1.0, V7, and its successors (4.xBSD, S3, S5, ...).  I
am at a loss to figure out why this was done.

Volume-Number: Volume 3, Number 15