LINUX.ORG.RU

непонятное поведение при получении SIGINT


0

1

привет.

в программе устанавливаю обработчик для SIGINT. срабатывает через раз. точнее - через три-четыре. но даже когда срабатывает, gdb все равно не запускается.

при попытке воспроизвести ситуацию в отдельном хеловорде - все срабатывает как часы.

скажите, из-за чего может быть такое непонятное поведение в реальном приложении?

★★★

Установка нескольких обработчиков SIGINT (в разных местах программы или разных нитях).

tailgunner ★★★★★
()

Слишком много возможных поводов: опции при установке/переустановке обработчика, поведение самого обработчика, многозадачность и управление флагами блокирования/ожидания/обработки сигналов, если монструозное приложение, то даже размер.

io ★★
()
Ответ на: комментарий от tailgunner

исключено. все обработчики устанавливаются в main`е.

niXman ★★★
() автор топика
Ответ на: комментарий от io

опции при установке/переустановке обработчика

обработчик устанавливается один раз. так:

static void set_signal_handler(int signum) {
	 struct sigaction new_action;
	 sigemptyset(&new_action.sa_mask);
	 new_action.sa_handler = signal_handler;
	 new_action.sa_flags = (signum == SIGUSR1) ? 0 : SA_RESETHAND|SA_ONSTACK;
	 if ( sigaction(signum, &new_action, 0) ) {
		  fprintf(stderr, "%s: %dn", "cant set handler for signal", errno);
	 }
}

поведение самого обработчика

в обработчике запускается gdb.

многозадачность

да, в программе есть потоки.

правление флагами блокирования/ожидания/обработки сигналов

такого нет.

если монструозное приложение, то даже размер.

ну...я бы сказал что приложение крупное.

niXman ★★★
() автор топика
Ответ на: комментарий от niXman

А SIGINT предполагается обрабатывать только раз? Точно SA_RESETHAND нужен?

No SA_RESETHAND:

Sleep
^CSIGINT
Sleep
^CSIGINT
...

SA_RESETHAND:
Sleep
^CSIGINT
Sleep
^C

Формально при многозадачности сигнал (по неким правилам), достается одной из нитей. При этом управление сигналами происходит с точностью до нити. Т.е. часть могут блокировать конкретные сигналы и т.п. Аналогичино альтернативный стек при создании нитей не наследуется (я уже писал, что он с точностью до таски, дабы избежать эффектов): The new thread does not inherit the creating thread’s alternate signal stack (sigaltstack(2)). Т.ч. только если сигнал достанется основной таске (а это не обязательно), то все прокатит, а иначе мимо кассы.

М.б. SIGINT блокировать на момент запуска задачек (дабы им маски хорошие достались), а потом уже разрешить обработку. Тогда SIGINT всегда достается основной. А может SA_ONSTACK тоже не злоупотреблять? Ну SEGV понимаю, а далее-то зачем.

io ★★
()
Ответ на: комментарий от niXman

Как вариант при старте каждой таски инициализировать все касающееся сигналов, в частности, не забыть sigaltstack - таки будет при SEGV полезен. Кстати, если таким образом искать зависшую таску, то не прокатит, т.к. адресат м.б. любой. Посему в gdb придется выполнять что-то в стиле thread apply all some_command, так чтобы для всех задач выдавалась разумная информация о вызовах (и только для текущей был бы например отброшен кусок обработчика сигнала), скорее всего это будут абстрактные системные вызовы. Возможно для SIGINT потребуется спеуиальный gdb-скрипт.

io ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.