Subject: Re: make -j and failure modes
To: Greywolf <greywolf@starwolf.com>
From: Robert Elz <kre@munnari.OZ.AU>
List: tech-userlevel
Date: 12/11/2003 18:12:32
    Date:        Wed, 10 Dec 2003 13:00:56 -0800 (PST)
    From:        Greywolf <greywolf@starwolf.com>
    Message-ID:  <Pine.NEB.4.58.0312101233090.895@rivendell.starwolf.com>

  | sol9$ ksh -ec '(false && echo bad); echo ok'
  | sol9$
  | 
  | This is what I would expect.  I don't understand why the exit status from
  | within a () should be treated any differently than the exit status from
  | a simple command.

The why takes looking at lots of examples, of what is reasonable
and what is common.

  | Inside the (), it does not produce no output because
  | it aborted before "echo bad"; it produces no output because the && evaluated
  | as false, causing the subshell -- the first command in the sequence --
  | to exit with an error.

yes (assuming "error" is shorthand for "non-zero exit status").

  | Because we provided the -e flag to the shell
  | running the command, and the first command in the sequence exited non-zero,

This goes back to what I just said in my earlier recent message.   You're
treating
	(false && echo bad)
as the "first command in the sequence" - because you know that out
there there's a sub-shell, which is a command, which runs stuff, and
then exits with some status or other.

But just look at it - that isn't really a command at all, it is a group
of two commands that are linked conditionally.

if you really wanted to force a subshell, you could use

	sh -c 'false && echo bad' ; echo ok

The it is clear, if the "sh" process exits with a non-zero
exit code (for any reason) and -e is set, then the echo (ok)
never happens.

Parentheses may look like "sh -c", they may even be implemented in
a quite similar way, but they are not the same syntax elements.

  | Of course all I can give is my word that I typed my expectations
  | before I ran my commands.

No, I believe you, your expectations just don't match mine.

  | For it to not
  | behave that way, by comparison to that legacy, means that somehow we have
  | broken sh and it needs to be fixed,

That's one interpretation.   The other is that it was always broken to
behave like that, and has since been fixed (in many versions of these
kinds of shells, and in posix anyway).

One indication of how irrelevant all this is, really, is the obscure
environment that was needed before anyone even noticed that this
difference exists...   Almost no-one uses -e - almost no-one (make
included) should ever use -e.

  | not that we need to mangle make in some nonstandard way

the suggestion certainly isn't anything non-standard - just to be
explicit when the scripts should exit (when they're not trivial so
everyone agrees) - this should work with all shells.

Nothing to comment on your expectations of "make -j", I have none.
If it were truly safe, and could work properly, the option would
never be needed - except perhaps to limit the number of parallel
processes make would use (perhaps to less than the number of processors
which would be a sensible default).   It isn't that safe, makefiles
need all kinds of special case assistance so make can work out what to
do and when - so just avoid -j (I appreciate that for some people who have
lots of cpu time, and lots of work, and want to get all the work done as
quickly as possible, by wasting as little of the available cpu as possible,
that it can help - as imperfect as it is - but I'd treat it like build.sh's
-E flag - for use only by those with nothing to loose...)

greywolf@starwolf.com said:
  | But the result has always been passed back.  I'm querulous as to why && is
  | actually in there; it doesn't need an exception since if the lhs fails,
  | everything else after the && of the failed lhs is not going to get executed
  | anyway, and a failed lhs of a && causes the entire logic string to be
  | evaluated as an error.

The && is there because the exit status of the command on the right of
the && is also ignored for -e purposes (as posix requires).

If you're writing command with && type logic in them, and you want the
script to exit, you should simply say so, at the appropriate point.
Don't rely upon -e making it all happen for you by magic.


greywolf@starwolf.com said:
| 	- HP-UX /bin/sh
| 	- AIX /bin/sh
| 	- IRIX /bin/sh [okay, so IRIX is dead.  Humour me.]
| 	- OSX /bin/sh [or is that BSD-sh?] 

With the exception of the last (which I'm not sure about), all
the rest are just SVR4 sh aren't they, with basically no changes at
all - whatever the result is on one of them, is almost certainly
going to be the result on all the others - solaris is most likely
the same (or could be if its sh5 were used - assuming it still has a
distinct sh5 from /bin/sh - it has been a while since I went there).


greywolf@starwolf.com said:
  | Something just dawned on me, here:
  | If
  | 	"(false && echo bad) || echo ok"
  | doesn't work as expected, then adding "|| exit $?" to the end of it isn't
  | going to make a difference. 

Of course not, but that command is going to run as expected on any
sane shell (that lets out csh, but never mind).   Commands like that
aren't the issue.

kre