Gentoo Development Guide

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.

Some portage-provided functions will automatically die upon failure. Others will not. It is for example safe to omit the || die after a call to epatch, but not emake. The reason is that external binaries are not able to call die that is a bash function. You can see what commands are external binaries with ls /usr/lib*/portage/bin/ebuild-helpers. In EAPI>=4 all ebuild-helpers automatically die upon failure.

Sometimes displaying additional error information beforehand can be useful. Use eerror to do this. See Messages.

It's best to use || die too often than too little.

die and Subshells

Warning

die will not work in a subshell.

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 epatch ${file} ; done

Using input redirection (see Abuse of cat) avoids this problem:

while read file ; do epatch ${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.

bunzip2 "${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.