LINUX.ORG.RU

не обрабатывается Ctrl+C на arm

 ,


1

2

скажу сразу, что тут, похоже, нужны сильные экстрасенсы и мощные телепаты.

в какой-то момент перестал обрабатываться Ctrl+C, но если кильнуть с SIGINT'ом, то все ok
в самой обработке ничего хитрого

void sighandler(int n)
{
    switch (n) {
        case SIGINT:
            printf("\n");
            g_stop = 1;
            printf("INTERRUPT SIGNAL CATCHED\n");
            break;
        case SIGALRM:
            printf("ALARM SIGNAL CATCHED\n");
            g_alarm = 1;
            break;
    };
}


внутри main(...):
#if 1
    if (signal(SIGALRM, sighandler) == SIG_ERR)
        printf("warning: cannot catch SIGALRM\n");
    if (signal(SIGINT, sighandler) == SIG_ERR)
        printf("warning: cannot catch SIGINT\n");
#else
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sighandler;
    if (sigemptyset(&sa.sa_mask))
        return 1;
/*
    if (sigaddset(&sa.sa_mask, SIGINT))
        return 1;
    if (sigaddset(&sa.sa_mask, SIGALRM))
        return 1;
*/
    if (sigaction(SIGALRM, &sa, NULL))
        printf("warning: cannot catch SIGALRM\n");
    if (sigaction(SIGINT, &sa, NULL))
        printf("warning: cannot catch SIGINT\n");
#endif


сначала работало, но одним прекрасным утром перестало :-\

при этом на x86_64 все ок...

есть какие-нибудь светлые идеи или видения? %)

p.s. а SIGALRM приходит и ловится
p.p.s. valgrind говорит, что все в порядке:

==26353== HEAP SUMMARY:
==26353==     in use at exit: 0 bytes in 0 blocks
==26353==   total heap usage: 54 allocs, 54 frees, 61,124 bytes allocated
==26353== 
==26353== All heap blocks were freed -- no leaks are possible
==26353== 
==26353== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 6)
--26353-- 
--26353-- used_suppression:     15 U1004-ARM-_dl_relocate_object
==26353== 
==26353== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 6)

Ответ на: комментарий от anonymous

Убедись, что они объявлены как volatile sig_atomic_t

спасибо, g_stop и g_alarm у меня были static int, но для порядка объявил их сейчас volatile sig_atomic_t

а еще забыл написать (сейчас подправлю), что SIGALRM приходит отлично

metawishmaster ★★★ ()

А может он просто не отправляется? Как ты его посылаешь? Через minicom? А как там всякие agetty поживают? А настройки терминала? setserial? stty? Конфиги может какие поменял? А просто kill -SIGINT с другого терминала сделать?

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

не, не изчезла..
там g_stop в подожденном потоке используется как флаг выхода, «while (g_stop != 1) {...»
но что «показательно», что Ctrl+C просто оюрубает прогу, как будто послали SIGKILL, если c другого терминала послать SIGINT, то выйдет красиво, с сообщением «INTERRUPT SIGNAL CATCHED»

т.е. по-ходу, после Ctrl+C до g_stop дело не доходит...

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

Как ты его посылаешь?

жму Ctrl+C :)

Через minicom?

не... тут круче - noname nx до десктопа, а в ней ssh до arm'овской железяки %)

А просто kill -SIGINT с другого терминала сделать?

выйдет красиво и вежливо, все ловится :)

а вот про «всякие agetty, настройки терминала, setserial, stty» - явроде ничего такого не менял, только «setterm -blank 0» и несколько route в rc.local добавил...

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

И еще printf() в обработчике сигнала скорее всего пользовать нельзя. Только write(), и может быть snprintf().

сейчас проверю... правда у меня и с printf работало, но про то, что его юзать в обработчиках не стоит я читал %)

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

Дело явно не в printf ) Тут риску в его использовании особого нет. Если только сигнал не придет, пока исполняется обработчик. Но это вряд ли

anonymous ()

Безумная догадка - C-c посылает вовсе не SIGINT. Раз ты говоришь, прога выходит всё же, то что-то всё же приходит. Но что?

Отлови ради лулзов также SIGHUP, SIGPIPE, SIGTERM. или воспользуйся каким-нибудь линуксовым аналогом ktrace

anonymous ()
Ответ на: комментарий от anonymous

а stty -a ничего крминального вроде не вернул


# stty -a
speed 38400 baud; rows 73; columns 270; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

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

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

anonymous ()
Ответ на: комментарий от anonymous

> Отлови ради лулзов также SIGHUP, SIGPIPE, SIGTERM.

это был SIGPIPE!
Спасибо! :)



а вот теперь совсем не важное, но очень интересное - SIGPIPE на Ctrl+C пришел только один раз, все остальное - SIGINT, даже после перезагрузки %)

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

Если ты будешь пускать прогу на своем компе, всё будет ок. А тут как я понял, sigint словила не твоя прога, а кто-то ещё. Вот, например, как ssh обрабатывает C-c

https://unix.stackexchange.com/questions/102061/ctrl-c-handling-in-ssh-sessio...

Решение: обрабатывать sigpipe так же, как ты обрабатываешь sigint (или похожим способом). Можешь использовать один и тот же обработчик

anonymous ()
Ответ на: комментарий от anonymous

окей, спасибо, буду знать :)

в определенных случаях прога порождает тред и «общается» с ним через RAW сокет

а еще я заметил, что при тех падениях код возврата был 130
но это

/* for robust mutexes */
#define EOWNERDEAD  130 /* Owner died */

мало о чем говорит %)

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

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

Тебе обязательно нужно блокировать SIGINT внутри дочернего потока, чтобы сигнал шел именно в главный тред. Иначе он придет в рандомный. Например, ты можешь закрыть дочерний, а родительский будет пытаться с ним сязаться и получит sigpipe. Если используешь pthread, то пользуйся pthread_sigmask.

Другой вариант - написать умный handler, который если что пошлет родительскому треду какой-то сигнал.

Короче без кода могу помочь только догадками

anonymous ()
Ответ на: комментарий от anonymous

Тебе обязательно нужно блокировать SIGINT внутри дочернего потока

а я чего-то с дуру думал, что дочерние наследуют handler'ы у родителя :-\

Короче без кода могу помочь только догадками

да стыдно эту фигню показывать пока - там 1200 строк с незавершенной логикой и на 75% неработающим на целевом девайсе функционалом %)

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

а я чего-то с дуру думал, что дочерние наследуют handler'ы у родителя :-\

Да, я не об этом. Когда обычный сигнал приходит, он ловится любым потоком. Стандарт не указывает, какой именно поток будет его обрабатывать. Соответственно, может ты не учитываешь это. Щас код гляну.

anonymous ()
Ответ на: комментарий от metawishmaster

Вот подозрительные места:

  pthread_spin_lock(&th_arg->lock);
  pthread_create(&rthr, NULL, receiver, th_arg);
  pthread_spin_lock(&th_arg->lock);

Два раза pthread_spin_lock()? Короче, я бы перепроверил блокировки ещё раз.

 sigemptyset(&set);
    sigaddset(&set, SIGINT);
    if (pthread_sigmask(SIG_BLOCK, &set, NULL)) {
        printf("error: cannot block SIGINT\n");
        return (void *)-1;
    }

А вот именно об этом я и говорил. Это ты после моего совета добавил, или изначально было так? Если после моего совета, интересно, что будет, если убрать обработку сигнала SIGPIPE. По-идее, всё должно быть OK. Короче тут надо вникать в то, что происходит, пожалуй я лучше не буду)) Тем более, уже всё работает

anonymous ()
Ответ на: комментарий от anonymous

[qute]
Вот подозрительные места:

  pthread_spin_lock(&th_arg->lock);
  pthread_create(&rthr, NULL, receiver, th_arg);
  pthread_spin_lock(&th_arg->lock);


тут все должно быть хорошо - в самом начале работы тред делает pthread_spin_unlock - это так жду создания потока, иначе теряются первые пакеты

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

Ну значит моя догадка была правильная

ага :)
не такая уж она была и «Безумная» :))

причем я еще до создания этого топика пытался циклом перехватить все 62 сигнала (знаю, что SIGKILL и кого-то еще нельзя перехватить), но что-то меня от этого отвлекло, и я обратился сюда %)

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

Форсируй псевдо-терминалы ключиком -t:

ssh -t ...
SIGINT Это в первую очередь функциональность терминалов. А у тебя ssh не посчитал целесообразным создавать псевдо-терминал

cvv ★★★★★ ()
Последнее исправление: cvv (всего исправлений: 1)
Ответ на: комментарий от cvv

Форсируй псевдо-терминалы ключиком -t
SIGINT Это в первую очередь функциональность терминалов. А у тебя ssh не посчитал целесообразным создавать псевдо-терминал

спасибо, но это же еще каждому «получателю» обяснять...

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

Эххх... Ну тогда не забывай что у этих сигналов разная природа. Если ты получил SIGINT это намек что приложению пора сворачиватся. Если же получен SIGPIPE это говорит о том что канал взаимодействия с пользователем (STDIN, STDOUT, STDERR) уже разрушен и ты можешь писать только в логи, точнее регулярные файлы.

cvv ★★★★★ ()
Последнее исправление: cvv (всего исправлений: 5)