[comp.lang.c] Weird syscall returns

mike@whuts.UUCP (BALDWIN) (07/08/87)

In article <1219@ius2.cs.cmu.edu>, edw@ius2.cs.cmu.edu (Eddie Wyatt) writes:
} > 
] > Almost agreed: but if a negative return code other than -1 is returned
} > the code doesn't react the same.

]     I can think of no Unix system call that doesn't return -1 on error.
} So I would say that it's a pretty good bet that "if (call(...) < 0)" and
] "if (call(...) == -1)" will act the same in all cases.

System V Release 1.0 had a PDP-11 only set of system calls collectively
named maus(2) which implemented a particularly obfusticated version of
shared memory.  Two of the calls, dismaus and switmaus, would sometimes
return -2 on successful completion.

}                                                         Though, one should
] always consult the man pages for return values if in doubt.

True, and the man pages are all very explicit.  The DIAGNOSTICS section
of (almost) every one contains the sentence, "Otherwise, a value of -1 is
returned and errno is set to indicate the error."  The man page *only*
guarantees -1, so why write potentially unportable code when it is so
*trivial* to make it correct?  It is _not_ just a style issue.
-- 
						Michael Scott Baldwin
			(not the opinions of)	AT&T Bell Laboratories
						{at&t}!whuts!mike

dave@sds.SciCom.MN.ORG (dave schmidt x194) (07/09/87)

>     I can think of no Unix system call that doesn't return -1 on error.

What about nice()?

mike@whuts.UUCP (BALDWIN) (07/10/87)

> >     I can think of no Unix system call that doesn't return -1 on error.
> What about nice()?

No, nice() *does* return -1 on error, so the original statement is true.
Unfortunately, it returns -1 on success (sometimes), which is a real pain.
The only way to be sure is to set errno to 0, then if nice returns -1 AND
errno is set, you have an error.  Yecch!  Although I'm just as queasy
about char *sbrk(), char *shmat(), and void (*signal/set())() returning -1
on error.  [Signal/set has even more rudeness with SIG_IGN (1) and SIG_HOLD
(2).  Hiding the rudeness with #define's (ala SIG_ERR (-1)) doesn't fix it.]
-- 
						Michael Scott Baldwin
			(not the opinions of)	AT&T Bell Laboratories
						{at&t}!whuts!mike

guy%gorodish@Sun.COM (Guy Harris) (07/10/87)

> >     I can think of no Unix system call that doesn't return -1 on error.
> 
> What about nice()?

From the S5R3 manual page:

	DIAGNOSTICS
	     Upon successful completion, "nice" returns the new nice
	     value minus 20.  Otherwise, a value of -1 is returned and
	     "errno" is set to indicate the error.

Other versions of "nice" may just return 0 on success, but they all
return -1 on error.

You may be thinking that -1 is a legitimate return value in the S5
"name", and you're right.  This is one of several botches in the UNIX
system call interface; to check for errors from "nice", you have to
clear "errno" before making the call, and test it after making the
call.  There are other calls, such as "ptrace", where this same
problem occurs.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

dg@wrs.UUCP (David Goodenough) (07/12/87)

In article <428@sds.SciCom.MN.ORG> dave@sds.SciCom.MN.ORG (dave schmidt x194) writes:
>>     I can think of no Unix system call that doesn't return -1 on error.
>
>What about nice()?

Well I don't know about your system, but on ours (ISI 68K - BSD 4.3)
there ain't no entry for nice in sect. 2 of the manual - it's in section 3.
What this tells me is that nice(3) isn't a direct system call. In fact it
goes via [sg]etpriority(2) which IS a system type call: witness the
following - First comes foo.c

main()
 {
    nice();
 }

and now comes the output from an 'adb foo' run

_main:		link	fp,#0
		jsr	_nice		; call to nice(3)
		unlk	fp
		rts

_nice:		link	fp,#-4
		clrl	_errno
		pea	0:w
		pea	0:w
		jsr	_getpriority	; call to getpriority(2)
		addql	#8,sp
		
			.
			.
			.

		pea	0:w
		jsr	_setpriority	; call to setpriority(2)
		lea	sp@(12),sp
		unlk	fp		; no traps (i.e. system entries)
		rts			; anywhere in nice
		.word 0

_getpriority:	moveml	sp@(4),#<d1,a0>
		moveq	#0x64,d0
		trap	#1		; HERE is the system entry trap
		bccs	0xec
		jmp	cerror
		rts

_setpriority:	moveml	sp@(4),#<d1,a0,a1>
		moveq	#0x60,d0
		trap	#1		; and the other
		bccs	0x100
		jmp	cerror
		rts

So order is restored!!
--
		dg@wrs.UUCP - David Goodenough

					+---+
					| +-+-+
					+-+-+ |
					  +---+

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/12/87)

There are several UNIX library routines in various implementations
that attempt to return a -1 value for a function whose return type
is (char *).  This is a holdover from the PDP-11 days where it didn't
matter, but these days we encounter environments for which there is
simply no such thing as (char *)-1.  I would hope that all these
botches could be fixed (certainly in any proposed standards!).  One
could do this in two phases:  Phase 1 -- change all applications and
library code that invokes such functions to check for either -1 or
NULL instead of just -1;  Phase 2 -- change these functions to return
NULL (of the appropriate type) on failure.  There have been similar
phased transitions before; we should get this fixed before it gets
worse.

guy%gorodish@Sun.COM (Guy Harris) (07/13/87)

> >>     I can think of no Unix system call that doesn't return -1 on error.
> >
> >What about nice()?
> 
> Well I don't know about your system, but on ours (ISI 68K - BSD 4.3)
> there ain't no entry for nice in sect. 2 of the manual - it's in section 3.
> What this tells me is that nice(3) isn't a direct system call. In fact it
> goes via [sg]etpriority(2) which IS a system type call...

Yes, but that's only the case on systems that have derived their
"nice" and "[sg]etpriority" implementations from the 4.[23]BSD one.
On other UNIX systems, "nice" *is* a system call, and it *does*
return -1 on error.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

dave@sds.SciCom.MN.ORG (dave schmidt x194) (07/15/87)

> > >     I can think of no Unix system call that doesn't return -1 on error.
> > 
> > What about nice()?
> 
> From the S5R3 manual page:
> 
> 	DIAGNOSTICS
> 	     Upon successful completion, "nice" returns the new nice
> 	     value minus 20.  Otherwise, a value of -1 is returned and
> 	     "errno" is set to indicate the error.
> 
> Other versions of "nice" may just return 0 on success, but they all
> return -1 on error.

How about "all reasonable versions return -1 on error"?  Here in the
backwaters of UNIX work-a-likes (aka XENIX), the manual says

	RETURN VALUE

	On successful completion, 'nice' returns the new nice value minue
	20.  Note that 'nice' is unusual in the way return codes are 
	handled.  It differs from most other system calls in two ways: the
	value -1 is a valid return code (in the case where the new nice
	value is 19), and the system call either works or ignores the
	request; THERE IS NEVER AN ERROR.  [my emphasis]

Personally, I'd regard ignoring the request as an error, but ...

guy%gorodish@Sun.COM (Guy Harris) (07/16/87)

(This is now a UNIX discussion rather than a C discussion, so I'm
moving it to comp.unix.questions.)

> > Other versions of "nice" may just return 0 on success, but they all
> > return -1 on error.
> 
> How about "all reasonable versions return -1 on error"?  Here in the
> backwaters of UNIX work-a-likes (aka XENIX), the manual says
> 
> 	 Note that 'nice' is unusual in the way return codes are 
> 	handled.  It differs from most other system calls in two ways: the
> 	value -1 is a valid return code (in the case where the new nice
> 	value is 19), and the system call either works or ignores the
> 	request; THERE IS NEVER AN ERROR.  [my emphasis]

Well, if this is really the case (i.e., they didn't just botch the
manual page), I'd be curious to know why they changed the AT&T code.
(Yes, Xenix *IS* derived from AT&T code; it's not a "rewritten from
scratch" "work-alike".)

My suspicion is that the documentation writers just got confused.
Try writing a program that attempts to reduce your "nice", and run
that program when not the super-user.  Have the program set "errno"
to zero before making the call, and check both the return code from
"nice" and the value of "errno" after making the call.  If the return
code isn't -1, and the value of "errno" isn't EPERM, somebody doing the
software screwed up.  If the return code is -1, and the value of
"errno" is EPERM, somebody doing the documentation screwed up.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

mpl@sfsup.UUCP (M.P.Lindner) (07/17/87)

In article <2337@whuts.UUCP>, mike@whuts.UUCP writes:
> In article <1219@ius2.cs.cmu.edu>, edw@ius2.cs.cmu.edu (Eddie Wyatt) writes:
> ] > Almost agreed: but if a negative return code other than -1 is returned
> } > the code doesn't react the same.
> 
> True, and the man pages are all very explicit.  The DIAGNOSTICS section
> of (almost) every one contains the sentence, "Otherwise, a value of -1 is
> returned and errno is set to indicate the error."  The man page *only*
> guarantees -1, so why write potentially unportable code when it is so
> *trivial* to make it correct?  It is _not_ just a style issue.
> -- 

Whoa there, let's take a look:
return code		sys call
0 or -1			access, acct, brk, chdir, chmod, chown, chroot, close,
			kill, link, mknod, mount, msgctl, pipe, plock, setuid,
			setgid, shmctl, stat, stime, umount, unlink, ustat,
			utime
non-negative int or -1	creat, dup, fork, lseek, msgget, nice, open,
			read, semget, shmget, time, times, ulimit, umask,
			uname, wait, write
bad things		sbrk, signal, semop, shmop, msgop
ha ha			exit, exec, pause, sync
can't tell from man	getpid, getuid, ioctl, profil, ptrace, semctl, setpgrp
or no error code	alarm, fcntl

So, what call returns a -1 as an error that can also return a negative
integer as a valid value?  NONE!  I know about maus, but since we're
talking portable, don't even mention it.  My claim is that since *most*
of the system calls return n >= 0 on success, it is more natural to test
for !(n >= 0) which is the same as n < 0 for failure.

Therefore, testing for < 0 is _not_ incorrect.  It _is_ a style issue.

edw@ius1.cs.cmu.edu (Eddie Wyatt) (07/17/87)

In article <1641@sfsup.UUCP>, mpl@sfsup.UUCP (M.P.Lindner) writes:
> In article <2337@whuts.UUCP>, mike@whuts.UUCP writes:
> > In article <1219@ius2.cs.cmu.edu>, edw@ius2.cs.cmu.edu (Eddie Wyatt) writes:
> > ] > Almost agreed: but if a negative return code other than -1 is returned
> > } > the code doesn't react the same.
> > 
> > True, and the man pages are all very explicit.  The DIAGNOSTICS section
> > of (almost) every one contains the sentence, "Otherwise, a value of -1 is
> > returned and errno is set to indicate the error."  The man page *only*
> > guarantees -1, so why write potentially unportable code when it is so
> > *trivial* to make it correct?  It is _not_ just a style issue.
> > -- 

	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	These aren't my comments, please don't credit them to me.  Give the
    proper credit to who ever wrote them.

> 
> Whoa there, let's take a look:
> return code		sys call
> 0 or -1			access, acct, brk, chdir, chmod, chown, chroot, close,
> 			kill, link, mknod, mount, msgctl, pipe, plock, setuid,
> 			setgid, shmctl, stat, stime, umount, unlink, ustat,
> 			utime
> non-negative int or -1	creat, dup, fork, lseek, msgget, nice, open,
> 			read, semget, shmget, time, times, ulimit, umask,
> 			uname, wait, write
> bad things		sbrk, signal, semop, shmop, msgop
> ha ha			exit, exec, pause, sync
> can't tell from man	getpid, getuid, ioctl, profil, ptrace, semctl, setpgrp
> or no error code	alarm, fcntl
> 
> So, what call returns a -1 as an error that can also return a negative
> integer as a valid value?  NONE!  I know about maus, but since we're
> talking portable, don't even mention it.  My claim is that since *most*
> of the system calls return n >= 0 on success, it is more natural to test
> for !(n >= 0) which is the same as n < 0 for failure.
> 
> Therefore, testing for < 0 is _not_ incorrect.  It _is_ a style issue.

    As others have pointed out, there are a few obsure Unix system calls
that will return an negetive number on success (dismaus, switmaus
PDP-11, some implementations of nice, one networking primative which
I forget its name).

   So its not totally a question of  style.  Neither is a total question
of correctness.  If your read or write calls are returning
negative bytes read or written then somethings has gone wrong.

  There are a few widely used systems calls which return values are
/should be/ understood - examples read, write, open ...  In case as
such, the issue of == -1 vs. < 0 becomes a style issue.

   I like to diverge a minute to the signal system call.  I think
this is a good example of bad interface design.  By intermixing
return value with error status information, one has created a sloppy
interface with incompatible return types (int and int (*func)()). 

  In general, the interface to any system call should only return
status information and modify input parameters to return values.
If this where the case, there would be no need for errno and no more
sloppy interfaces like signal.  The type of the error could be return
as an indication of an error with one value reserved to indicate success.
This method has been the the approach MACH has taken.

-- 

					Eddie Wyatt

e-mail: edw@ius1.cs.cmu.edu

guy%gorodish@Sun.COM (Guy Harris) (07/17/87)

> Whoa there, let's take a look:
> return code		sys call
> non-negative int or -1	creat, dup, fork, lseek, msgget, nice, open,
> 
> So, what call returns a -1 as an error that can also return a negative
> integer as a valid value?  NONE!  I know about maus, but since we're
> talking portable, don't even mention it.  My claim is that since *most*
> of the system calls return n >= 0 on success, it is more natural to test
> for !(n >= 0) which is the same as n < 0 for failure.

Whoa there, let's take a *careful* look this time.  "nice" *can* return a
negative integer ("Upon successful completion, 'nice' returns the new nice
value minus 20," from the S5R2 manual page, and the new "nice" value
can be less than 20).  It is OK to test for "n < 0" if the call is
guaranteed to return a non-negative integer on success, but NOT if it
can return a negative integer.

"nice" is even worse, because (at least on systems where it returns
the new "nice" value) it can return -1 on *success*!  You can only
test this by clearing "errno", making the call, and testing "errno"
after the call.  (The same is true of "ptrace".)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

mike@whuts.UUCP (BALDWIN) (07/17/87)

In article <1641@sfsup.UUCP>, mpl@sfsup.UUCP (M.P.Lindner) writes:
> So, what call returns a -1 as an error that can also return a negative
> integer as a valid value?  NONE!

Sorry, but you've misclassified nice(2).  It returns the new nice value
(range 0-39) minus 20.  Thus, it can return anything in the range -20 to
19 on SUCCESSFUL completion.

>                                           My claim is that since *most*
> of the system calls return n >= 0 on success, it is more natural to test
> for !(n >= 0) which is the same as n < 0 for failure.
> Therefore, testing for < 0 is _not_ incorrect.  It _is_ a style issue.

I claim it is more natural and correct to test for whatever the manual
page says.  E.g., fcntl(2) DIAGNOSTICS in SVR3.0 says for most cmds taht
the successful completion return is "Value other than -1."  Therefore, if
you code it as "if (fcntl() < 0)" then you are NOT PORTABLE, because nothing
guarantees that it won't return -2 on success in the future.

For a great many system calls, it doesn't matter currently.  But why make
it more difficult in the future if something changes in a way that's
compatible with the docs but not with your code?
-- 
Michael Scott Baldwin		{at&t}!whuts!mike	I only speak
AT&T Bell Laboratories		+1 201 386 3052		for myself!

paul@whuts.UUCP (HO) (07/22/87)

In article <1641@sfsup.UUCP>, mpl@sfsup.UUCP (M.P.Lindner) writes:
> So, what call returns a -1 as an error that can also return a negative
> integer as a valid value?  NONE!  

Ever wonder why in /usr/src/cmd/nice.c, nice is called without
having its return value checked?

	Paul Ho