C / нажатие Ctrl + C вызывает сигнал несколько раз? - PullRequest
0 голосов
/ 01 июня 2011

После нажатия ctrl+c я получаю следующий вывод. Что касается кода, почему строка signal 2 was raised, exiting... появляется несколько раз, даже если я нажал клавиши только один раз?

Мой вывод выглядит так:

-sh-2.05b# ./proxyp 192.168.1.100
shmget id: 65538
signal 10 was raised, should write out
signal 10 was raised, should write out
signal 2 was raised, exiting...
signal 2 was raised, exiting...
signal 2 was raised, exiting...
signal 2 was raised, exiting...
signal 2 was raised, exiting...

Мой источник для потока, обрабатывающего сигналы, выглядит так (программа еще не завершена, поэтому не беспокойтесь о совместной памяти или о чем-либо еще):

/* global variables */
wuint32 sh_id;

/* signal handlers */
void sgn_exit_programm(int sig, siginfo_t *siginfo, void *context);
void sgn_write_stdout(int sig, siginfo_t *siginfo, void *context);

/* main thread */
void *mgmtSrvcThread(port_configuration_data *p) {
struct sigaction sig_action_exit, sig_action_write;

shared_data sh_data = p->sh_mem;
sh_id = sh_data.shm_id;

wuint32 shm, shmid;

if((shmid = shmget(MEMKEY, MAXMYMEM, 0666)) < 0) {
    perror("shmget");
    exit(1);
}

if((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
    perror("shmat");
    exit(1);
}

/* Set up the structure to specify the new action */
sig_action_exit.sa_handler = sgn_exit_programm;
sig_action_write.sa_handler = sgn_write_stdout;
sigaction(SIGINT, &sig_action_exit, NULL);
sigaction(SIGUSR1, &sig_action_write, NULL);

while(1) {
    sleep(1);
}

return (void*)0;
}


void sgn_write_stdout(int sig, siginfo_t *siginfo, void *context) {
    printf("signal %d was raised, should write out\n", sig);
}


void sgn_exit_programm(int sig, siginfo_t *siginfo, void *context)
{
    printf("signal %d was raised, exiting...\n", sig);
    sleep(1);
    exit(0);
}

Может быть, немного больше об этом: я работаю с несколькими потоками внутри мастера. Один из потоков является просто потоком управления, который должен обрабатывать вывод в stdout и обрабатывать сигналы. Источник выше. Внутри разделяемой памяти должно появиться сообщение, что поток должен записать в стандартный вывод. Вот и все.

обновление после добавления дополнительного кода уверен, что обработчик вызывается более одного раза.

void sgn_exit_programm(int sig, siginfo_t *siginfo, void *context)
{
printf("signal %d was raised, exiting...\n", sig);
fflush(stdout);
if(shmdt(data) < 0) {
    perror("shmdt");
    exit(1);
} else {
    printf("detached successful\n");
}

sleep(1);
exit(0);
}

И это вывод, как вы видите, задача отсоединения выполняется один раз успешно:

-sh-2.05b# ./proxyp 192.168.1.100
shmget id: 65538
signal 2 was raised, exiting...
detached successful
signal 2 was raised, exiting...
shmdt: Invalid argument
signal 2 was raised, exiting...
shmdt: Invalid argument
signal 2 was raised, exiting...
shmdt: Invalid argument
signal 2 was raised, exiting...
shmdt: Invalid argument

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 01 июня 2011

Не «делайте работу» в вашем обработчике сигналов. Установите флаг и обработайте его в своей обычной программе. Работа с сигналами и потоками - тоже интересное дело. Я предполагаю, что все становится запутанным, потому что несколько потоков видят сигнал и пытаются реагировать на него. Я считаю, что «основной» поток - единственный поток, который должен принимать сигнал, но он может быть неопределенным (это было давно, извините).

Эта ссылка также может быть полезна (первый сайт в поиске Google): http://uw714doc.sco.com/en/SDK_sysprog/PTL_ThdsSigs.html

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

0 голосов
/ 01 июня 2011

Может быть оператором printf в обработчике сигнала SIGINT, находящимся в буфере stdout, поэтому, когда завершается каждый поток, он печатает этот оператор и затем завершается.

Можете ли вы поставить fflush(stdout); заявление после printf() заявления и попробовать его снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...