[comp.unix.internals] asserts and unexpected returns

jfh@rpp386.cactus.org (John F. Haugh II) (10/31/90)

In article <4093@awdprime.UUCP> daveb@bach.austin.ibm.com (Dave Burton) writes:
>The only way for a SVR2,3 assert() to return is _if_ SIGIOT is not
>SIG_DFL.  Most programs do not blithely SIG_IGN all signals.  Further,
>BSD/AIX/other asserts can _never_ return.  So, yes, I always% assume
>failing asserts() never return - that is their design.  As for portability,
>see below.
>
>% given the caveat of SIGIOT peculiarities on SVR2,3 systems

yes, quite a few of my programs do run off on a tear and blithely
ignore all of their signals.

one thing you are ignoring is how many systems have the behavior
which i describe.  it is not just limited to SVR2 and SVR3, it
includes every AT&T release prior to SVR2, such as 3.0, 4.0, 7th
Edition, etc, and non-AT&T versions of UNIX-like operating systems
as well.  it is reasonable to expect abort() to return if SIGIOT
is ignored.  it doesn't matter what you think assert() is designed
to do, there is so much prior art which contradicts your expectation.
unfortunately there is also some prior art which agrees with what
you are saying, and that is why i say to expect the worst - you
lose nothing if you do, but if you don't you may have expected
return conditions you aren't prepared to handle.

i checked the old X3J11 draft i have - it was silent on the
issue.  now, i don't know if ANSI C requires abort() to exit,
but if it doesn't, we still have this problem in ANSI C.  using
unspecified or undefined behavior is the very definition of
non-portable.  even if ANSI C, X/OPEN and half a dozen other
standards all agree with you, there is simply too much prior
experience with other behavior.

>It is obvious that you did not read what I wrote.
>Repeat after me: "assert() is a macro, not a function."
>If I put an exit() after an assert() call, it looks like:

then don't do it that way.

>		if (assert(argc==2) == -1)
>			exit(1);
>
>Oh.  Syntax error.  Looking at assert.h reveals the definition:
>
>	#define assert(EX) if (EX) ; else _assert("EX", __FILE__, __LINE__)
>
>Gee, "Uncle Fred", how do you put a conditional exit() in your code?
>Surely you wouldn't do:
>
>		assert(argc==2),exit(1);
>
>would you?  What happens when NDEBUG is #define'd?  Syntax error.
>The only way to put an exit() after a failing assert() is to
>rework the macro, which is not portable.

this is too easy.

you put a conditional.  then you put an exit.  this gives you
a conditional exit statement.  most programmers don't have
trouble with this.  many of them even write code like

	if (! (chunk = malloc (sizeof *chunk))) {
		perror ("oops");
		exit (1);
	}

how about (gee, just a suggestion, i normally charge for my
programming lessons, so this isn't a programming lesson)

	if (! (chunk = malloc (sizeof *chunk))) {
		perror ("oops");
		assert (chunk != 0);
		exit (1);
	}

now, i'd never actually do this, so don't think i am advocating
this exact code fragment.  but gee, dave, it isn't that hard.

>|but the kernel assert() function is not defined
>|in the System V Programmer's Reference Manual sitting next to me.
>|i checked the namelist on the kernel running here.
>
>This could be my fault for not accurately describing the kernel assert
>mechanism for you.  The _macro_ name (it _won't_ appear in any namelist,
>just like user asserts) is ASSERT().  It invokes assfail() the same way
>user assert() invokes _assert().  And assfail() will _not_ return.
>Refer to <sys/debug.h>.

% grep -y ASSERT /usr/include/sys/debug.h
%

hmmm.  no ASSERT (or assert) in my <sys/debug.h>.  perhaps this really
is just another IBMism.  perhaps this is implementation specific
details which have no bearing in a discussion of portable programming
practices?

furthermore, i don't recall any requirement in any of the documentation
i've read requiring assert() invoke _assert() or assfail() or any of
the stuff you keep talking about.  please, try to limit this discussion
to documented features.  let's start with this documented feature -

	"assert(S)

	 if expression is false (zero), it displays ... on the
	 standard error file and aborts."

and then this documented feature -

	"abort(S)

	 abort can return control if the calling process is set
	 to catch or ignore SIGIOT ..."

5.0 documentation is even more explicit.

>I admit, I did look at the sources to verify my understanding
>before posting to the net.  That's generally considered wise.
>Perhaps you would fare better if you did the same.

are you in the habit of violating your non-disclosure agreements
with IBM and AT&T just so you can make your postings?  many of the
people in this group have access to source code as well, but most
of us don't run off and read it then report what we find to the
net.

just so you get to see how this =really= works in the =real=
world, try this -

Script is typescript, started Wed Oct 31 08:09:42 1990
rpp386-> cat abort.c
#include <signal.h>
#include <assert.h>
#include <stdio.h>

main (argc, argv)
int	argc;
char	**argv;
{
	signal (SIGIOT, SIG_IGN);
	assert (argc == 2);
	printf ("hi dave!\n");
}
rpp386-> cc -o abort abort.c
abort.c
rpp386-> ./abort
Assertion failed: expr, file abort.c, line 10
hi dave!
rpp386-> exit
Script done Wed Oct 31 08:10:00 1990
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (11/01/90)

In article <18662@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
: In article <4093@awdprime.UUCP> daveb@bach.austin.ibm.com (Dave Burton) writes:
: >I admit, I did look at the sources to verify my understanding
: >before posting to the net.  That's generally considered wise.
: >Perhaps you would fare better if you did the same.
: 
: are you in the habit of violating your non-disclosure agreements
: with IBM and AT&T just so you can make your postings?  many of the
: people in this group have access to source code as well, but most
: of us don't run off and read it then report what we find to the
: net.

But the best sources of advice will generally double-check the sources and
then pretend they wrote it out of their head.  :-)

[To whom it may concern:  the undersigned does not at this time have access
to any AT&T proprietary sources.  (Which is obviously why I've been giving
such bad advice lately...  :-)]

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov

daveb@nostromo.austin.ibm.com (Dave Burton) (11/09/90)

[ I'm ignoring advice from the adage "Never argue with a fool." ]
[ But this is the last time :-) ]

In article <4093@awdprime.UUCP> daveb@bach.austin.ibm.com (Dave Burton) writes:
# The only way to put an exit() after a failing assert() is to
# rework the macro, which is not portable.

In article <18662@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
| you put a conditional.  then you put an exit.  this gives you
| a conditional exit statement.  most programmers don't have
| trouble with this.  many of them even write code like
| 
| 	if (! (chunk = malloc (sizeof *chunk))) {
| 		perror ("oops");
| 		exit (1);
| 	}
| 
| how about (gee, just a suggestion, i normally charge for my
| programming lessons, so this isn't a programming lesson)
| 
| 	if (! (chunk = malloc (sizeof *chunk))) {
| 		perror ("oops");
| 		assert (chunk != 0);
| 		exit (1);
| 	}
| 
| now, i'd never actually do this, so don't think i am advocating
| this exact code fragment.  but gee, dave, it isn't that hard.

If this is your idea of "programming lessons", I hope your charge
is that nobody reveals you taught them.  You're nobody's teacher
(especially after this thread) and not my "Uncle Fred".
Lose the flippant 'tude, dude, and get back to reality.

Your example is ludicrous.  Of what use would assert be in such a case?
Then you disclaim your example with "now, i'd never actually do this".
Why did you give this example then?  If you have a clear idea how to
do what you propose, show us.

#|but the kernel assert() function is not defined
#|in the System V Programmer's Reference Manual sitting next to me.
#|i checked the namelist on the kernel running here.

I ignored this the first time around:
The System V Programmer's Reference Manual also does not include
namei() or major(), does this mean they're not there, or can't be
relied upon in kernel code?

| hmmm.  no ASSERT (or assert) in my <sys/debug.h>.  perhaps this really
| is just another IBMism.  perhaps this is implementation specific ...

SVR2.1 has it.  My SVR3.2 (ESIX) has it.  I've used it in AT&T's SVR3.2
i386 and 3b2 offerings.  I'd say it's not an IBMism, nor is it implementation
specific.  The UNIX SVR3 BCI Driver Development Guide documents it quite well.
See pp 13:13,14 for a discussion.  It's also quite well known to SV
kernel hacks.

| furthermore, i don't recall any requirement in any of the documentation
| i've read requiring assert() invoke _assert() or assfail() or any of
| the stuff you keep talking about.

Nobody ever said there was.  I mentioned _assert() and assfail()
simply to enlighten you, since you didn't seem to understand about the
macro nature of assert(), and couldn't find ASSERT/assert in your kernel's
namelist.  It was never mentioned in the context of portability except
to elucidate why various assert() "band-aids" were not portable.

# I admit, I did look at the sources to verify my understanding
# before posting to the net.  That's generally considered wise.
# Perhaps you would fare better if you did the same.

| are you in the habit of violating your non-disclosure agreements
| with IBM and AT&T just so you can make your postings?  many of the
| people in this group have access to source code as well, but most
| of us don't run off and read it then report what we find to the
| net.

I certainly didn't "run off and read it then report what [I found] to the net."
It was more like:  "Hmm.  I think John is wrong.  I've used assert()
before, and it never returns.  Perhaps it's only that way on BSD and SVRx
systems.  Before I post,  I'd better confirm with other implementations."

Possibly the only "trade secret" I revealed was that IBM's abort() can
be trusted to not return.  That's positive press.  But go ahead, forward
my posting(s) to my management and IBM security (as if they haven't
already screened them) and let's see who gets their hand slapped.

| just so you get to see how this =really= works in the =real=
| world, try this -
| [ paraphrase of the demo program I wrote to show John's folly ]

Grrrr!  This really pisses me off, John.  I _know_ what that program does.
If you really want to brow-beat me, modify it to make the assert() _always_,
_portably_ exit, without repeating the test in the assertion itself
(which you were already flamed for once).
--
Dave Burton
inet: daveb@bach.austin.ibm.com
uucp: cs.utexas.edu!ibmchs!auschs!nostromo!daveb

jfh@rpp386.cactus.org (John F. Haugh II) (11/12/90)

In article <4157@awdprime.UUCP> daveb@bach.austin.ibm.com (Dave Burton) writes:
>I ignored this the first time around:
>The System V Programmer's Reference Manual also does not include
>namei() or major(), does this mean they're not there, or can't be
>relied upon in kernel code?

go check the kernel on AIX V3.1, you will find that it does not
include namei() as a kernel service.  clearly this proves that
you can't rely on non-standard or undocumented features.  don't
believe me - go check the source code.  no namei().

now will you give up?  you can't seem to accept that on some
system assert() and abort() return to their invoker, and now
you go claiming namei() is a common kernel service.  please,
quit while you are just slightly behind.
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

mikep@dirty.csc.ti.com (Michael A. Petonic) (11/13/90)

In article <18717@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>In article <4157@awdprime.UUCP> daveb@bach.austin.ibm.com (Dave Burton) writes:
>>I ignored this the first time around:
>>The System V Programmer's Reference Manual also does not include
>>namei() or major(), does this mean they're not there, or can't be
>>relied upon in kernel code?
>
>go check the kernel on AIX V3.1, you will find that it does not
>include namei() as a kernel service.  clearly this proves that
>you can't rely on non-standard or undocumented features.  don't
>believe me - go check the source code.  no namei().

This is rapidly degenerating into a flame war (uh, too late).

But, since it's already here, let me add...

Come on, John!  If you've got enough UNIX history to know what the hell
namei() does, then you'll no doubt be smart enough to realize that it's
not going to be a straightforward implementation on AIX with the filesystem
*sufficiently* different than System V.  If you're in this far, you'd better
know what the f*ck you're doing.

Your off-the-cuff/hard-and-fast rules are boring us, John.  You wouldn't
want to be known as a bore, would you (uh, too late).

-MikeP

jim@segue.segue.com (Jim Balter) (11/14/90)

In article <18717@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>[...]  you can't seem to accept that on some
>system assert() and abort() return to their invoker, [...]

No one has claimed that assert cannot be made to return on some systems,
yet this is at least the third time that you have responded to some *other*
point as though that claim were being made.  Can you say *strawman*?
Since I previously explicitly pointed this out and yet you ignored it (you
did respond to other parts of my posting, so you did receive it), the only
explanation I can see is bad faith.  While there is plenty of room in the
information groups for disagreement, there is none for bad faith.

>will you give up?  you can't seem to accept that on some
>system assert() and abort() return to their invoker, and now
>you go claiming namei() is a common kernel service.  please,
>quit while you are just slightly behind.

This isn't a contest, John.

jfh@rpp386.cactus.org (John F. Haugh II) (11/14/90)

In article <4643@segue.segue.com> jim@segue.segue.com (Jim Balter) writes:
>No one has claimed that assert cannot be made to return on some systems,
>yet this is at least the third time that you have responded to some *other*
>point as though that claim were being made.  Can you say *strawman*?

The other objector to my claim that assert() may return has claimed
that implementations which have an assert() that can be made to return
should be ignored, despite the fact that AT&T UNIX 5.2.1 (and all releases
that I know of before it) has exactly this behavior.  Dave has repeatedly
stated that for all "real" UNIX's assert() never returns, without
accepting that this criteria is only true for some flavors of AIX and
BSD.  In any case, Dave is arguing against reality - the exception proves
the argument in this case, and the argument was that assert cannot be
relied on to always exit.  Providing the single counterexample of SCO
Xenix 2.2.3 (and of course, AT&T UNIX 5.2.1) disproves his statement
that assert() always exits.  [ And yes, he has made that claim, before
you state that this is a strawman. ]

Anyhow, this is getting old, and has long strayed away from the original
topic, which was to be careful of unexpected returns.
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

boyd@necisa.ho.necisa.oz (Boyd Roberts) (11/16/90)

In article <18733@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>...  In any case, Dave is arguing against reality - the exception proves
>the argument in this case, and the argument was that assert cannot be
>relied on to always exit.

And nor can your CPU be relied upon to function after you've stuck an
axe through it.  Your whole argument is based on the premise that
things don't work `normally' after you've broken them.  Get serious.


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''