Differences between test-kickseed and real execution
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
kickseed (Ubuntu) |
Fix Committed
|
Undecided
|
Hamilton Turner |
Bug Description
I've encountered an odd issue, perhaps someone can help me isolate. When I run test-kickseed on the %pre block below, 'handler/pre.sh' reports a getopt failure parsing the %pre options **and continues executing**. (support for --log is the feature I'm currently adding into kickseed, the issue is that it continues executing)
---------------
%pre --log=foobar.log
echo should pass
%end
----------------
When I attempt an install with this %pre **kickseed halts**. This is because the call to getopt returns a non-zero exit code and errexit (set -e) is turned on. Halting seems to be the proper behavior, but test-kickseed continues executing.
I originally thought it had something to do with my shell or my getopt implementation, but I wrote a small test.sh file (below) that shows that "set -e" works in a manner consistent with what I'm seeing during an actual install. This test file halts when running "bash -e test.sh" or "sh -e test.sh", and test-kickseed does not.
-------
#!/bin/sh -e
bar () {
set -o | grep errexit
TEMP=`getopt -o '' -l foo: -- "$@"`
echo good stuff
}
bar "--foo=bar"
bar "--log"
-------
$ ./test.sh
errexit on
good stuff
errexit on
getopt: unrecognized option '--log'
-------
So what's happening with test-kickseed? I did add a debug statement in handlers/pre.sh before the call to getopt, and errexit is definitely turned on. I added a debug statement after getopt, and the error code is 1. This seems like it should be halting, but for some insane reason it's not - with set -e I shouldn't even see the output telling me the error code, the program should terminate automatically.
PS - I have moved all my getopt calls to their own lines, so this is not an issue with "set -e and ||"
I'm not insane, but I am wrong! This is indeed caused by "set -e and ||". Specifically, the difference between how test-kickseed and initrd-kickseed call the kickseed function.
test-kickseed calls:
RET=0
(kickseed "$1") || RET=$?
This means that kickseed() is called as "part of any command executed in a && or || list", and therefore errexit has no effect anywhere inside of the kickseed function when it is called from test-kickseed.
This is clearly intentional, but it also caused me substantial confusion due to different behavior, so I'll put in a tiny commit that causes a big warning message to be printed when $RET != 0. Currently the exit code is just being returned to the user, and it would take a particularly savvy user to check the exit code of test-kickseed every time and interpret that a non-zero means that the install will behave differently than the test.