]> git.lizzy.rs Git - plan9front.git/blob - sys/man/9/error
ndb/dns: allow multiple txt, nullrr, cert, key and sig records (thanks kvik)
[plan9front.git] / sys / man / 9 / error
1 .TH ERROR 9
2 .SH NAME
3 error, nexterror, poperror, waserror \- error handling functions
4 .SH SYNOPSIS
5 .ta \w'\fL#define 'u
6 .B
7 void    error(char*)
8 .PP
9 .B
10 void    nexterror(void)
11 .sp 0.1
12 .PP
13 .B
14 #define poperror() (up->nerrlab--)
15 .PP
16 .B
17 #define waserror() (setlabel(&up->errlab[up->nerrlab++]))
18 .SH DESCRIPTION
19 The kernel handles error conditions using non-local gotos,
20 similar to
21 .IR setjmp (2),
22 but using a stack of error labels to implement nested exception handling.
23 This simplifies many of the internal interfaces by eliminating the need
24 for returning and checking error codes at every level of the call stack,
25 at the cost of requiring kernel routines to adhere to a strict discipline.
26 .PP
27 Each process has in its defining kernel
28 .B Proc
29 structure a stack of labels,
30 .B NERR
31 (currently 64)  elements deep.
32 A kernel function that must perform a clean up or recovery action on an error
33 makes a stylised call to
34 .IR waserror ,
35 .IR nexterror
36 and
37 .IR poperror :
38 .IP
39 .EX
40 .DT
41 if(waserror()){
42         /* recovery action */
43         nexterror();
44 }
45 /* normal action */
46 poperror();
47 .EE
48 .PP
49 When called in the normal course of events,
50 .I waserror
51 registers an error handling block by pushing its label onto the stack,
52 and returns zero.
53 The return value of
54 .I waserror
55 should be tested as shown above.
56 If non-zero (true), the calling function should perform the needed
57 error recovery, ended by a call to
58 .I nexterror
59 to transfer control to the next location on the error stack.
60 Typical recovery actions include deallocating memory, unlocking resources, and
61 resetting state variables.
62 .PP
63 Within the recovery block,
64 after handling an error condition, there must normally
65 be a call to
66 .I nexterror
67 to transfer control to any error recovery lower down in the stack.
68 The main exception is in the outermost function in a process,
69 which must not call
70 .I nexterror
71 (there being nothing further on the stack), but calls
72 .I pexit
73 (see
74 .IR kproc (9))
75 instead,
76 to terminate the process.
77 .PP
78 When the need to recover a particular resource has passed,
79 a function that has called
80 .I waserror
81 must
82 remove the corresponding label from the stack by calling
83 .IR poperror .
84 This
85 must
86 be done before returning from the function; otherwise, a subsequent call to
87 .I error
88 will return to an obsolete activation record, with unpredictable but unpleasant consequences.
89 .PP
90 .I Error
91 copies the given error message, which is limited to
92 .B ERRMAX
93 bytes, into the
94 .B Proc.errstr
95 of the current process,
96 enables interrupts by calling
97 .I spllo
98 .RI ( native
99 only),
100 and finally calls
101 .I nexterror
102 to start invoking the recovery procedures currently stacked by
103 .IR waserror .
104 The file
105 .B /sys/src/9/port/error.h
106 offers a wide selection of predefined error messages, suitable for almost any occasion.
107 The message set by the most recent call to
108 .I error
109 can be obtained within the kernel by examining
110 .B up->error
111 and in an application, by using the
112 .L %r
113 directive of
114 .IR print (2).
115 .PP
116 A complex function can have nested error handlers.
117 A
118 .I waserror
119 block will follow the acquisition of a resource, releasing it
120 on error before calling
121 .I nexterror,
122 and a
123 .I poperror
124 will precede its release in the normal case.
125 For example:
126 .IP
127 .EX
128 .DT
129 void
130 outer(Thing *t)
131 {
132     qlock(t);
133     if(waserror()){      /* A */
134         qunlock(t);
135         nexterror();
136     }
137     m = mallocz(READSTR, 0);
138     if(m == nil)
139         error(Enomem);  /* returns to A */
140     if(waserror()){     /* B */
141         free(m);
142         nexterror();    /* invokes A */
143     }
144     inner(t);
145     poperror();         /* pops B */
146     free(m);
147     poperror();         /* pops A */
148     qunlock(t);
149 }
150 .sp 1v
151 void
152 inner(Thing *t)
153 {
154     if(t->bad)
155         error(Egreg);   /* returns to B */
156     t->valid++;
157 }
158 .EE
159 .SH SOURCE
160 .B /sys/src/9/port/proc.c
161 .SH CAVEATS
162 The description above has many instances of
163 .IR should ,
164 .IR will ,
165 .I must
166 and
167 .IR "must not" .
168 .SH SEE ALSO
169 .IR panic (9),
170 .IR kproc (9),
171 .IR splhi (9)