Правильный способ завершения приложения C, чтобы обеспечить завершение критических разделов? - PullRequest
0 голосов
/ 01 ноября 2011

У меня есть обработчик перехвата отключения, определенный в ОДНОМ поточном приложении C.

int main(int argc, char * argv[]){
    //Shutdown hook for CTRL-C
    (void) signal(SIGINT, shutdownHook);
    ...
    ...
}

Поэтому, когда пользователь нажимает CTRL-C, инициируется перехват отключения ...

void shutdownHook(int sig){
    rc = wmq_sender_stop(errorStr);
    if (rc != 0){
        printf("\n%s\n", errorStr);
    }
    while(transactionRunning == TRUE){
        sleep(1);
        printf("Transaction still running\n");
    }
    ....
    ....
}

Вы можете видеть выше, что я вызываю подпрограмму "wmq_sender_stop" (в разделяемой библиотеке), которая по существу устанавливает переменную в значение FALSE, чтобы завершить цикл в этой разделяемой библиотеке.

int wmq_sender_stop(char errorStr[ERROR_STR_LEN]){
       running = FALSE;
       ...
}

И эта переменная "выполняется"остановит (надеюсь) основной цикл, работающий в этой общей библиотеке.

while(running == TRUE){
...
...
}

Проблема, с которой я сталкиваюсь, заключается в том, что на моем компьютере с Linux все работает на 100% ... но когда я устанавливаю приложение на БОЛЬШОМ мощном компьютереСервер вызывает "wmq_sender_stop" и устанавливает переменную в порядке, но кажется, что приложение работает на сервере слишком быстро, чтобы позволить переменной "while (running == TRUE)" выйти ..... ИЛИ это простослишком быстрое возвращение к основному приложению, и цикл «while (транзакция == ИСТИНА)» просто непрерывно работает ...

По существу на БОЛЬШОМ сервере, если я нажимаю CRTL-C, непрерывно выводится следующееэкран:

Transaction still running
Transaction still running
Transaction still running
Transaction still running
Transaction still running
Transaction still running
...

Возможно, мне нужно создать потоки здесь и иметь взаимосвязь между ними, но это не простой способ элегантно разрешить «цикл в общей библиотеке» для завершения «критического кода / транзакций»перед выключением даже на очень быстрых серверах?И почему это работает на моем ноутбуке Linux?

А если мне нужно использовать нити, каков наилучший и самый быстрый способ их распространения?В настоящее время я использую CALLBACKS .... но я не уверен, что лучший IPC для потоков?

Спасибо за помощь, очень признателен

Lynton

Ответы [ 2 ]

2 голосов
/ 01 ноября 2011

Убедитесь, что runningtransactionRunning тоже) объявлено как volatile.В противном случае компилятор C может при некоторых обстоятельствах кэшировать свое значение.Пока что volatile следует понимать как означающее «это значение может быть изменено обработчиком сигнала».

Обратите внимание, что вы должны быть осторожны с кодом, подобным этому:

rc = wmq_sender_stop(errorStr);

Есливы делаете это в обработчике сигналов, вам лучше надеяться, что эту функцию безопасно вызывать из обработчика сигналов.Большинство функций нет.(Даже функции, которые можно безопасно вызывать из нескольких потоков, небезопасны для вызова из обработчика сигнала.)

Последняя проблема заключается в том, что если ваш код однопоточный, но вы никогда не вернетесь из обработчика сигнала, какВаш основной цикл должен выйти?Обработчик сигналов работает в одном из существующих потоков вашего приложения.Как правило, единственное, что вы хотите сделать в обработчике сигнала, это изменить значение глобальной переменной, помеченной volatile, а затем вернуть.

0 голосов
/ 01 ноября 2011

Почему бы просто не позвонить wmq_sender_stop(), а затем оставить обработчик сигнала через return. Цикл в разделяемой lib завершится, и так будет работать ваше приложение, не так ли?

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