2 * libdpkg - Debian packaging suite library routines
3 * ehandle.c - error handling
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
32 #include <dpkg/macros.h>
33 #include <dpkg/i18n.h>
34 #include <dpkg/progname.h>
35 #include <dpkg/color.h>
36 #include <dpkg/ehandle.h>
38 /* Incremented when we do some kind of generally necessary operation,
39 * so that loops &c know to quit if we take an error exit. Decremented
40 * again afterwards. */
41 volatile int onerr_abort
= 0;
45 struct cleanup_entry
{
46 struct cleanup_entry
*next
;
49 void (*call
)(int argc
, void **argv
);
56 struct error_context
{
57 struct error_context
*next
;
65 error_handler_func
*func
;
70 error_printer_func
*func
;
74 struct cleanup_entry
*cleanups
;
79 static struct error_context
*volatile econtext
= NULL
;
82 * Emergency variables.
84 * These are used when the system is out of resources, and we want to be able
85 * to proceed anyway at least to the point of a controlled shutdown.
88 struct cleanup_entry ce
;
92 * Emergency error message buffer.
94 * The size is estimated using the following heuristic:
95 * - 6x255 For inserted strings (%.255s &c in fmt; and %s with limited
97 * - 1x255 For constant text.
98 * - 1x255 For strerror().
99 * - And the total doubled just in case.
105 * Default fatal error handler.
107 * This handler performs all error unwinding for the current context, and
108 * terminates the program with an error exit code.
111 catch_fatal_error(void)
113 pop_error_context(ehflag_bombout
);
118 print_fatal_error(const char *emsg
, const void *data
)
120 fprintf(stderr
, "%s%s:%s %s%s:%s %s\n",
121 color_get(COLOR_PROG
), dpkg_get_progname(), color_reset(),
122 color_get(COLOR_ERROR
), _("error"), color_reset(), emsg
);
126 print_abort_error(const char *etype
, const char *emsg
)
128 fprintf(stderr
, _("%s%s%s: %s%s:%s\n %s\n"),
129 color_get(COLOR_PROG
), dpkg_get_progname(), color_reset(),
130 color_get(COLOR_ERROR
), etype
, color_reset(), emsg
);
133 static struct error_context
*
134 error_context_new(void)
136 struct error_context
*necp
;
138 necp
= malloc(sizeof(*necp
));
140 ohshite(_("out of memory for new error context"));
141 necp
->next
= econtext
;
142 necp
->cleanups
= NULL
;
150 set_error_printer(struct error_context
*ec
, error_printer_func
*func
,
153 ec
->printer
.func
= func
;
154 ec
->printer
.data
= data
;
158 set_func_handler(struct error_context
*ec
, error_handler_func
*func
)
160 ec
->handler_type
= HANDLER_TYPE_FUNC
;
161 ec
->handler
.func
= func
;
165 set_jump_handler(struct error_context
*ec
, jmp_buf *jump
)
167 ec
->handler_type
= HANDLER_TYPE_JUMP
;
168 ec
->handler
.jump
= jump
;
172 error_context_errmsg_free(struct error_context
*ec
)
174 if (ec
->errmsg
!= emergency
.errmsg
)
180 error_context_errmsg_set(struct error_context
*ec
, char *errmsg
)
182 error_context_errmsg_free(ec
);
186 static int DPKG_ATTR_VPRINTF(1)
187 error_context_errmsg_format(const char *fmt
, va_list args
)
193 va_copy(args_copy
, args
);
194 rc
= vasprintf(&errmsg
, fmt
, args_copy
);
197 /* If the message was constructed successfully, at least we have some
198 * error message, which is better than nothing. */
200 error_context_errmsg_set(econtext
, errmsg
);
203 /* If there was any error, just use the emergency error message buffer,
204 * even if it ends up being truncated, at least we will have a big part
206 rc
= vsnprintf(emergency
.errmsg
, sizeof(emergency
.errmsg
), fmt
, args
);
208 /* Return failure only if we get truncated. */
209 if (rc
>= (int)sizeof(emergency
.errmsg
))
212 error_context_errmsg_set(econtext
, emergency
.errmsg
);
219 push_error_context_func(error_handler_func
*handler
,
220 error_printer_func
*printer
,
221 const void *printer_data
)
223 struct error_context
*ec
;
225 ec
= error_context_new();
226 set_error_printer(ec
, printer
, printer_data
);
227 set_func_handler(ec
, handler
);
232 push_error_context_jump(jmp_buf *jumper
,
233 error_printer_func
*printer
,
234 const void *printer_data
)
236 struct error_context
*ec
;
238 ec
= error_context_new();
239 set_error_printer(ec
, printer
, printer_data
);
240 set_jump_handler(ec
, jumper
);
245 push_error_context(void)
247 push_error_context_func(catch_fatal_error
, print_fatal_error
, NULL
);
251 print_cleanup_error(const char *emsg
, const void *data
)
253 print_abort_error(_("error while cleaning up"), emsg
);
257 run_cleanups(struct error_context
*econ
, int flagsetin
)
259 static volatile int preventrecurse
= 0;
260 struct cleanup_entry
*volatile cep
;
261 struct cleanup_entry
*ncep
;
262 struct error_context recurserr
, *oldecontext
;
263 jmp_buf recurse_jump
;
264 volatile int i
, flagset
;
266 if (econ
->printer
.func
)
267 econ
->printer
.func(econ
->errmsg
, econ
->printer
.data
);
269 if (++preventrecurse
> 3) {
271 print_cleanup_error(_("too many nested errors during error recovery"), NULL
);
277 oldecontext
= econtext
;
279 for (i
=0; i
<NCALLS
; i
++) {
280 if (cep
->calls
[i
].call
&& cep
->calls
[i
].mask
& flagset
) {
281 if (setjmp(recurse_jump
)) {
282 run_cleanups(&recurserr
, ehflag_bombout
| ehflag_recursiveerror
);
283 error_context_errmsg_free(&recurserr
);
285 memset(&recurserr
, 0, sizeof(recurserr
));
286 set_error_printer(&recurserr
, print_cleanup_error
, NULL
);
287 set_jump_handler(&recurserr
, &recurse_jump
);
288 econtext
= &recurserr
;
289 cep
->calls
[i
].call(cep
->argc
,cep
->argv
);
291 econtext
= oldecontext
;
294 flagset
&= cep
->cpmask
;
295 flagset
|= cep
->cpvalue
;
297 if (cep
!= &emergency
.ce
) free(cep
);
304 * Push an error cleanup checkpoint.
306 * This will arrange that when pop_error_context() is called, all previous
307 * cleanups will be executed with
308 * flagset = (original_flagset & mask) | value
309 * where original_flagset is the argument to pop_error_context() (as
310 * modified by any checkpoint which was pushed later).
312 void push_checkpoint(int mask
, int value
) {
313 struct cleanup_entry
*cep
;
316 cep
= malloc(sizeof(*cep
) + sizeof(void *));
319 ohshite(_("out of memory for new cleanup entry"));
322 for (i
=0; i
<NCALLS
; i
++) { cep
->calls
[i
].call
=NULL
; cep
->calls
[i
].mask
=0; }
323 cep
->cpmask
= mask
; cep
->cpvalue
= value
;
324 cep
->argc
= 0; cep
->argv
[0]= NULL
;
325 cep
->next
= econtext
->cleanups
;
326 econtext
->cleanups
= cep
;
330 cleanup_entry_new(void (*call1
)(int argc
, void **argv
), int mask1
,
331 void (*call2
)(int argc
, void **argv
), int mask2
,
332 unsigned int nargs
, va_list vargs
)
334 struct cleanup_entry
*cep
;
341 cep
= malloc(sizeof(*cep
) + sizeof(void *) * (nargs
+ 1));
343 if (nargs
> array_count(emergency
.args
))
344 ohshite(_("out of memory for new cleanup entry with many arguments"));
345 e
= errno
; cep
= &emergency
.ce
;
347 cep
->calls
[0].call
= call1
; cep
->calls
[0].mask
= mask1
;
348 cep
->calls
[1].call
= call2
; cep
->calls
[1].mask
= mask2
;
349 cep
->cpmask
=~0; cep
->cpvalue
=0; cep
->argc
= nargs
;
351 va_copy(args
, vargs
);
354 *argv
++ = va_arg(args
, void *);
357 cep
->next
= econtext
->cleanups
;
358 econtext
->cleanups
= cep
;
359 if (cep
== &emergency
.ce
) {
361 ohshite(_("out of memory for new cleanup entry"));
368 push_cleanup(void (*call
)(int argc
, void **argv
), int mask
,
369 unsigned int nargs
, ...)
373 va_start(args
, nargs
);
374 cleanup_entry_new(call
, mask
, NULL
, 0, nargs
, args
);
379 push_cleanup_fallback(void (*call1
)(int argc
, void **argv
), int mask1
,
380 void (*call2
)(int argc
, void **argv
), int mask2
,
381 unsigned int nargs
, ...)
385 va_start(args
, nargs
);
386 cleanup_entry_new(call1
, mask1
, call2
, mask2
, nargs
, args
);
390 void pop_cleanup(int flagset
) {
391 struct cleanup_entry
*cep
;
394 cep
= econtext
->cleanups
;
395 econtext
->cleanups
= cep
->next
;
396 for (i
=0; i
<NCALLS
; i
++) {
397 if (cep
->calls
[i
].call
&& cep
->calls
[i
].mask
& flagset
)
398 cep
->calls
[i
].call(cep
->argc
,cep
->argv
);
400 if (cep
!= &emergency
.ce
) free(cep
);
404 * Unwind the current error context by running its registered cleanups.
407 pop_error_context(int flagset
)
409 struct error_context
*tecp
;
412 econtext
= tecp
->next
;
414 /* If we are cleaning up normally, do not print anything. */
415 if (flagset
& ehflag_normaltidy
)
416 set_error_printer(tecp
, NULL
, NULL
);
417 run_cleanups(tecp
, flagset
);
419 error_context_errmsg_free(tecp
);
423 static void DPKG_ATTR_NORET
424 run_error_handler(void)
427 /* We arrived here due to a fatal error from which we cannot recover,
428 * and trying to do so would most probably get us here again. That's
429 * why we will not try to do any error unwinding either. We'll just
430 * abort. Hopefully the user can fix the situation (out of disk, out
431 * of memory, etc). */
432 print_abort_error(_("unrecoverable fatal error, aborting"), econtext
->errmsg
);
433 error_context_errmsg_free(econtext
);
437 if (econtext
== NULL
) {
438 print_abort_error(_("outside error context, aborting"),
439 _("an error occurred with no error handling in place"));
441 } else if (econtext
->handler_type
== HANDLER_TYPE_FUNC
) {
442 econtext
->handler
.func();
443 internerr("error handler returned unexpectedly!");
444 } else if (econtext
->handler_type
== HANDLER_TYPE_JUMP
) {
445 longjmp(*econtext
->handler
.jump
, 1);
447 internerr("unknown error handler type %d!", econtext
->handler_type
);
451 void ohshit(const char *fmt
, ...) {
455 error_context_errmsg_format(fmt
, args
);
462 ohshitv(const char *fmt
, va_list args
)
464 error_context_errmsg_format(fmt
, args
);
469 void ohshite(const char *fmt
, ...) {
475 /* First we construct the formatted message. */
477 rc
= error_context_errmsg_format(fmt
, args
);
480 /* Then if there was no error we append the string for errno. Otherwise
481 * we just use the emergency error message buffer, and ignore the errno
482 * value, as we will probably have no space left anyway. */
486 rc
= asprintf(&errmsg
, "%s: %s", econtext
->errmsg
, strerror(e
));
488 error_context_errmsg_set(econtext
, errmsg
);
495 do_internerr(const char *file
, int line
, const char *func
, const char *fmt
, ...)
500 error_context_errmsg_format(fmt
, args
);
503 fprintf(stderr
, "%s%s:%s:%d:%s:%s %s%s:%s %s\n", color_get(COLOR_PROG
),
504 dpkg_get_progname(), file
, line
, func
, color_reset(),
505 color_get(COLOR_ERROR
), _("internal error"), color_reset(),
508 error_context_errmsg_free(econtext
);