Error handling
Importance of error handling
Decent error handling is important because:
- Errors must be detected before Portage tries to install a broken or incomplete package onto the live filesystem. If build failures aren't caught, a working package could be unmerged and replaced with nothing.
-
When receiving bug reports, it is a lot easier to figure out what went wrong
if you know exactly which call caused the error, rather than just knowing
that, say, something somewhere in
src_compile
broke. - Good error handling and notification can help cut down on the number of bug reports received for a package.
The die
function
The die
function should be used to indicate a fatal error and abort the
build. Its parameters should be the message to display.
Although die
will work with no parameters, a short message should always be
provided to ease error identification. This is especially important when a
function can die in multiple places.
Ebuild helpers automatically die on failure. Some eclass-provided functions will automatically die upon failure, others will not. Developers should check the eclass reference when in doubt.
Sometimes displaying additional error information beforehand can be useful. Use
eerror
to do this. See Messages.
die
on almost all external commands in ebuilds.
die
and subshells
die
will not work in a subshell unless you are using EAPI=7 and onwards.
The following code will not work as expected, since the die
is inside a
subshell:
[[ -f foorc ]] && ( update_foorc || die "Couldn't update foorc!" )
The correct way to rewrite this is to use an if
block:
if [[ -f foorc ]] ; then
update_foorc || die "Couldn't update foorc!"
fi
When using pipes, a subshell is introduced, so the following is unsafe:
cat list | while read file ; do eapply ${file} ; done
Using input redirection (see Abuse of cat) avoids this problem:
while read file ; do eapply ${file} ; done < list
The assert
function and PIPESTATUS
When using pipes, simple conditionals and tests upon $?
will not
correctly detect errors occurring in anything except the final command in
the chain. To get around this, bash provides the PIPESTATUS
variable,
and Portage provides the assert
function to check this variable.
bzip2 -dc "${DISTDIR}/${VIM_RUNTIME_SNAP}" | tar -xf -
assert
If you need the gory details of PIPESTATUS
, see the bash manpage.
Most of the time, assert
is enough.
The nonfatal
command
If a non-zero exit status from an ebuild helper function is expected, you may
call it under the nonfatal
function. Instead of dying on failure,
the command will then return non-zero exit status, as in the following example:
src_test() {
if ! nonfatal emake check ; then
local a
eerror "Tests failed. Looking for files to add to your bug report..."
while IFS='' read -r -d $'\0' a ; do
eerror " ${a}"
done < <(find "${S}" -type f -name '*.log' -print0)
die "Make check failed"
fi
}