Как добавить код в стандартный обработчик сигнала? - PullRequest
3 голосов
/ 12 сентября 2011

У меня есть приложение C, работающее в Linux, где мне нужно добавить код в стандартный обработчик сигналов.Идея состояла в том, чтобы настроить мой обработчик, сохраняя указатель на стандартный и вызывать сохраненный обработчик из моего кода.К сожалению, ни signal (), ни sigaction () не возвращают указатель на стандартный обработчик.Вместо этого они оба возвращают NULL.Есть ли способ выполнить пользовательскую обработку и продолжить стандартную обработку без удаления пользовательского обработчика и повторной отправки того же сигнала?

Ответы [ 2 ]

3 голосов
/ 12 сентября 2011

Нет «стандартного обработчика сигнала»;вместо этого ядром выполняется действие по умолчанию, когда сигнал не обрабатывается.Если вы хотите что-то сделать, когда сигнал получен, а затем перейти к действию по умолчанию, вы можете сделать следующее в конце вашего обработчика сигнала:

sigset_t set;
signal(sig, SIG_DFL);
raise(sig);
sigemptyset(&set);
sigaddset(&set, sig);
sigprocmask(SIG_UNBLOCK, &set, 0);

Это предполагает, что вы использовали sigaction дляустановите ваш обработчик сигнала и не указывайте флаги SA_NODEFER или SA_RESETHAND.Также возможно достичь того, что вы хотите, используя эти флаги и просто вызывая raise, но это имеет ужасные условия гонки, если сигнал доставляется дважды в быстрой последовательности, поэтому вы не должны этого делать;вместо этого используйте предложенный мной метод.

Редактировать: На самом деле вам не нужно ничего делать с маской сигналов, поскольку возврат из обработчика сигналов восстановит старую маску сигналов.Просто это должно работать:

signal(sig, SIG_DFL);
raise(sig);
return;
0 голосов
/ 12 сентября 2011

Когда вызов метода signal () или sigaction () возвращает NULL, это подразумевает SIG_DFL (т.е. обработчик сигнала по умолчанию)

Если вы используете signal (), обработчик должен быть сброшен при вызове обработчика, вы можете поднять повышение (SIGNAL) как последняя строка в обработчике сигналов, и она должна вызывать обработчик по умолчанию.

Если вы используете sigaction (), вы должны передать SA_RESETHAND в качестве одного из флагов, что позволит вам использовать вызов Повышения (SIGNAL) в этом обработчике.

Подавляющее большинство обработчиков сигналов по умолчанию завершают работу приложения, поэтому эта замена «одним выстрелом» будет работать. Можете добавить вызов sigaction () после вызова функции вставки для повторного сохранения нового обработчика, например

void sighandler(int signum)
{
    // Do my stuff
    raise(signup);
    signal(signum, sighandler);
}
...