Итак, у меня есть библиотека (не написанная мной), которая, к сожалению, использует abort()
для устранения определенных ошибок.На уровне приложения эти ошибки исправимы, поэтому я хотел бы обработать их вместо того, чтобы пользователь видел сбой.В итоге я пишу такой код:
static jmp_buf abort_buffer;
static void abort_handler(int) {
longjmp(abort_buffer, 1); // perhaps siglongjmp if available..
}
int function(int x, int y) {
struct sigaction new_sa;
struct sigaction old_sa;
sigemptyset(&new_sa.sa_mask);
new_sa.sa_handler = abort_handler;
sigaction(SIGABRT, &new_sa, &old_sa);
if(setjmp(abort_buffer)) {
sigaction(SIGABRT, &old_sa, 0);
return -1
}
// attempt to do some work here
int result = f(x, y); // may call abort!
sigaction(SIGABRT, &old_sa, 0);
return result;
}
Не очень элегантный код.Поскольку этот шаблон в конечном итоге должен повторяться в нескольких местах кода, я хотел бы немного упростить его и, возможно, обернуть его в объект многократного использования.Моя первая попытка заключается в использовании RAII для обработки установки / отключения обработчика сигналов (это необходимо сделать, потому что каждая функция требует различной обработки ошибок).Поэтому я придумал следующее:
template <int N>
struct signal_guard {
signal_guard(void (*f)(int)) {
sigemptyset(&new_sa.sa_mask);
new_sa.sa_handler = f;
sigaction(N, &new_sa, &old_sa);
}
~signal_guard() {
sigaction(N, &old_sa, 0);
}
private:
struct sigaction new_sa;
struct sigaction old_sa;
};
static jmp_buf abort_buffer;
static void abort_handler(int) {
longjmp(abort_buffer, 1);
}
int function(int x, int y) {
signal_guard<SIGABRT> sig_guard(abort_handler);
if(setjmp(abort_buffer)) {
return -1;
}
return f(x, y);
}
Конечно, тело function
намного проще и яснее , но сегодня утром мне пришла в голову мысль. Это гарантированно сработает? Вот мои мысли:
- Никакие переменные не являются изменчивыми или меняются между вызовами на
setjmp
/ longjmp
. - Я
longjmp
вхожу в местоположение в том же фрейме стека, что и setjmp
и return
, обычно, поэтому я позволяю коду выполнить код очистки, который компилятор выдал на выходеТочки функции. - Кажется, что работает как ожидалось.
Но я все еще чувствую, что это, вероятно, неопределенное поведение.Что вы, ребята, думаете?