Subject: Re: make -j and failure modes
To: Robert Elz <kre@munnari.OZ.AU>
From: James Chacon <jmc@NetBSD.org>
List: tech-userlevel
Date: 12/10/2003 12:53:24
On Thu, Dec 11, 2003 at 01:26:35AM +0700, Robert Elz wrote:
>     Date:        Wed, 10 Dec 2003 10:45:04 -0600
>     From:        James Chacon <jmc@NetBSD.org>
>     Message-ID:  <20031210164503.GA6589@netbsd.org>
> 
>   | Both of these are excluded from -e tests anyways. It lists exceptions for
>   | AND and OR.
> 
> Yes, it also explicitly says just "simple commands".
> Then it goes on and excludes even some of those, so it isn't
> even all simple commands (but certainly nothing which isn't simple
> counts, and a compound command certainly is not simple).

This is where the syntax is non-exact. If it only applies to simple commands,
why bother to list exceptions for things that aren't even simple commands
to begin with (ala the IF/WHILE etc tests). 

>   | For what reason? The command in question exited non-zero for some reason. 
>   | Whatever the reason was it's concern. The parent process though is set to
>   | exit (via -e) for anything that returns non-zero and this would meet that
>   | criteria since it isn't in the exception list for -e.
> 
> Then how would you handle a Makefile that happened to contain
> 
> 	(cd dir && test -f file && cat file)
> 
> If file doesn't exist, that will exit 1, as the last command
> executed is te test, which failed (same if dir doesn't exist).
> 
> But that isn't what is wanted - the intent there is simply to cat
> the file, if it exists, and do nothing if it doesn't.
> 

Hmmm..Ok. I buy this one. I agree where you're going now. Just took a better
example to get me there :-)

> This is why the && exception exists in the rules - nothing else makes
> sense.   How can doing it in a sub-shell (needed so the cd doesn't
> change the parent shell) possibly be intended to change the result?
> That makes no sense.

Based on the above I see this now.

> 
>   | No. It was the subshell exiting non-zero that's being ignored.
>   | Run a make rule of
>   | 
>   | all:
>   |         (false)
>   |         echo foo
>   | 
>   | via make -j (which feeds that into sh -ev) and echo foo will be printed.
>   | Not exactly expected behavior from make at all.
> 
> No.   But that is make's problem.
> Not the shells - make is using sh incorrectly.

Due to the feeding into sh, yes. 

> 
> Make -j is simply broken (in yet another way) - just avoid it.

Actually I can't find other ways it's not working correctly (as long as
proper analysis of your Makefiles has been done and .WAIT's added 
appropriately).

This is fixed via adding '|| exit $?' as Ben suggested so I'll probably start
reviewing Makefiles for this shortly. In addition the man page for make
needs a much clearer explanation of the implications of -j and command
execution (since non-compat mode is different than traditional make in this
respect with all the commands flowing through 1 shell instance).

James