1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
<?xml version="1.0" encoding="UTF-8"?>
<guide self="ebuild-writing/error-handling/">
<chapter>
<title>Error handling</title>
<section>
<title>Importance of error handling</title>
<body>
<p>
Decent error handling is important because:
</p>
<ul>
<li>
Errors must be detected <e>before</e> 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.
</li>
<li>
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 <c>src_compile</c> broke.
</li>
<li>
Good error handling and notification can help cut down on the number of bug
reports received for a package.
</li>
</ul>
</body>
</section>
<section>
<title>The <c>die</c> function</title>
<body>
<p>
The <c>die</c> function should be used to indicate a fatal error and abort the
build. Its parameters should be the message to display.
</p>
<p>
Although <c>die</c> 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.
</p>
<p>
Ebuild helpers automatically die on failure. Some eclass-provided functions
will automatically die upon failure, others will not. Developers should check
the <uri link="::eclass-reference/">eclass reference</uri> when in doubt.
</p>
<p>
Sometimes displaying additional error information beforehand can be useful. Use
<c>eerror</c> to do this. See <uri link="::ebuild-writing/messages/"/>.
</p>
<note>
You should use <c>die</c> on almost all external commands in ebuilds.
</note>
</body>
</section>
<section>
<title><c>die</c> and subshells</title>
<body>
<warning>
<c>die</c> <b>will not work in a subshell unless you are using EAPI=7 and onwards</b>.
</warning>
<p>
The following code will not work as expected, since the <c>die</c> is inside a
subshell:
</p>
<codesample lang="ebuild">
[[ -f foorc ]] && ( update_foorc || die "Couldn't update foorc!" )
</codesample>
<p>
The correct way to rewrite this is to use an <c>if</c> block:
</p>
<codesample lang="ebuild">
if [[ -f foorc ]] ; then
update_foorc || die "Couldn't update foorc!"
fi
</codesample>
<p>
When using pipes, a subshell is introduced, so the following is unsafe:
</p>
<codesample lang="ebuild">
cat list | while read file ; do eapply ${file} ; done
</codesample>
<p>
Using input redirection (see <uri link="::tools-reference/cat/#Abuse of cat"/>)
avoids this problem:
</p>
<codesample lang="ebuild">
while read file ; do eapply ${file} ; done < list
</codesample>
</body>
</section>
<section>
<title>The <c>assert</c> function and <c>PIPESTATUS</c></title>
<body>
<p>
When using pipes, simple conditionals and tests upon <c>$?</c> will not
correctly detect errors occurring in anything except the final command in
the chain. To get around this, bash provides the <c>PIPESTATUS</c> variable,
and Portage provides the <c>assert</c> function to check this variable.
</p>
<codesample lang="ebuild">
bzip2 -dc "${DISTDIR}/${VIM_RUNTIME_SNAP}" | tar -xf -
assert
</codesample>
<p>
If you need the gory details of <c>PIPESTATUS</c>, see the bash manpage.
Most of the time, <c>assert</c> is enough.
</p>
</body>
</section>
<section>
<title>The <c>nonfatal</c> command</title>
<body>
<p>
If a non-zero exit status from an ebuild helper function is expected, you may
call it under the <c>nonfatal</c> function. Instead of dying on failure,
the command will then return non-zero exit status, as in the following example:
</p>
<codesample lang="ebuild">
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
}
</codesample>
</body>
</section>
</chapter>
</guide>
|