2013-04-01 11 views
3

Я лично ненавижу подобные вопросы, но я застрял. У меня есть программа, которую я пытаюсь запустить на Ubuntu 12.4(kernal: Linux 3.2.0-39-generic-pae # 62-Ubuntu SMP i686 i686 i386 GNU/Linux; компилятор: gcc (Ubuntu/Linaro 4.6 .3-1ubuntu5) 4.6.3):Аварийный сигнал на Ubuntu 12.4

#include <stdio.h> 
#include <signal.h> 
#include <unistd.h> 

/* 
* sleep1.c 
*  purpose show how sleep works 
*  usage sleep1 
*  info sets handler, sets alarm, pauses, then returns 
*/ 

int main() 
{ 
    void onbell(int); 

    printf("about to sleep for 4 seconds\n"); 
    signal(SIGALRM, onbell);   /* catch it */ 
    alarm(4);     /* set clock */ 
    pause();     /* do nothing */ 
    printf("Morning so soon?\n");   /* back to work */ 
    return 0; 
} 

void 
onbell(int s) 
{ 
    printf("Alarm received from kernel\n"); 
} 

проблема есть, SIGALRM никогда не приходит через. Если я бегу Strace на нем, последние три строки:

rt_sigaction(SIGALRM, {0x80484c1, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 
alarm(4)        = 0 
pause(

Пауза никогда не возвращается. Когда я запускаю тот же код в системе, которая сообщает себя с Kernal: Linux 2.6.24-32-generic i686 GNU/Linux; Компилятор: GCC (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4) тот же код работает с Трассированием на нем показывает:

rt_sigaction(SIGALRM, {0x8048470, [ALRM], SA_RESTART}, {SIG_DFL}, 8) = 0 
alarm(4)        = 0 
pause()         = ? ERESTARTNOHAND (To be restarted) 
--- SIGALRM (Alarm clock) @ 0 (0) --- 
write(1, "Alarm received from kernel\n", 27Alarm received from kernel 
) = 27 

Любой идея, почему тревога никогда не взяла на Ubuntu 12.4 системы или что можно сделать, чтобы выяснить, что происходит?

+0

«Когда я запускаю тот же код в другой системе», уже скомпилирован? Или скомпилировать его из источника снова? –

+0

компиляция из источника на другой системе – Nate

+0

Можете ли вы опубликовать свои версии компилятора для каждой версии и версии ядра? –

ответ

0

Я думаю, что проблема заключается в том, что сигнал никогда не срабатывает. В конце концов, strace показывает, что rt_sigaction возвращает 0, указывая на успех в настройке расположения сигнала. Я думаю, что сигнал SIGALRM никогда не отправляется вообще.

EDIT: Кажется, это был случай. Надеюсь, @Gonzalo не возражает против ссылки на VirtualBox ticket he posted под названием «SIGALRM никогда не срабатывает». Вы сказали, что тестируете виртуальную коробку. Кажется, это отражает это поведение.

+0

Спасибо за код, это хорошая мысль. Переключение не помогает, процесс все еще не проходит через функцию паузы. – Nate

+0

Я согласен с этим анализом, – Nate

+0

@Nate Да, редко можно обвинить ядро ​​(поскольку мы исключили компилятор). Сначала я подозревал, что это может быть ядро, но потом снова я не знал, что вы работаете в среде VirtualBox, ха-ха. Надеюсь, ваша проблема решена сейчас. –

1

Вы не можете безопасно вызывать printf() или справедливое количество других функций ввода-вывода из обработчика сигнала. Иногда это работает, но это ненадежно. Это не безопасно для асинхронного сигнала. См. Это для списка других: http://man7.org/linux/man-pages/man7/signal.7.html

Это иногда «случайно» работает, но люди думают, что это вообще приемлемо.

Попробуйте вместо этого увеличивать переменную внутри обработчика сигнала, а затем проверять его значение, изменяющееся вне обработчика сигнала.

+0

Спасибо за комментарий. Я опустошил функцию _bell_ всего содержимого, и процесс все еще не проходит через функцию _pause_. – Nate

+1

Кроме того, я не вижу ничего плохого в том, что вы делаете, и, хотя я уверен, что вы не хотите это слышать, он отлично работает здесь, но я не запускаю Ubuntu. Любой шанс вы можете скомпилировать его в другой системе (а не Ubuntu, какой-то другой дистрибутив Linux) и скопировать его, чтобы посмотреть, что произойдет? Возможно, это проблема с программными цепочками/библиотекой. –

+0

:) Спасибо, просто попробовал вытащить скомпилированную версию со второй машины на машину Ubuntu, и такое же поведение происходит. – Nate

Смежные вопросы