Подтвердить что ты не робот

Предотвращение MSYS bash 'от процессов убийства, которые ловушки ^ C

У меня есть консольное приложение Windows (портировано из Unix), которое изначально предназначалось для чистого выхода, когда оно получило ^C (Unix SIGINT). Чистый выход в этом случае связан с ожиданием, возможно, довольно долгое время, когда удаленные сетевые подключения закрываются. (Я знаю, что это не нормальное поведение ^C, но я не в состоянии его изменить). Программа однопоточная.

Я могу ловить ^C с помощью signal(SIGINT) (как в Unix) или SetConsoleCtrlHandler. Либо работает правильно, когда программа запускается под CMD.EXE. Однако, если я использую оболочку "bash", которая поставляется с MSYS (я использую среду MinGW для сборки программы, так как это позволяет мне повторно использовать make файлы Unix), то программа принудительно завершает какое-то случайное, короткое время ( менее 100 миллисекунд) после ^C. Это неприемлемо, поскольку, как я уже упоминал, программе необходимо дождаться завершения удаленных сетевых подключений.

Очень вероятно, что люди захотят запустить эту программу в MSYS bash. Кроме того, этот эффект нарушает набор тестов. Я не смог найти какой-либо способ обойти проблему либо изнутри программы (идеально), либо с помощью настроек на оболочке (допустимо). Кто-нибудь может что-нибудь рекомендовать?

4b9b3361

Ответ 1

У меня была такая же проблема - я написал программу с обработчиком SIGINT/SIGTERM. Этот обработчик выполнял очистку, которая иногда занимала некоторое время. Когда я запускал программу изнутри msys bash, ctrl-c вызовет мой обработчик SIGINT, но он не завершится - программа была прервана (как бы "снаружи" ), прежде чем она сможет завершить ее очистку -up.

На основе ответа phs и ответа на аналогичный вопрос: fooobar.com/questions/159014/..., я придумал следующее решение. Это безумно просто, и у него могут быть некоторые побочные эффекты, которые я еще не обнаружил, но он устранил проблему для меня.

Создайте файл ~/.bashrc со следующей строкой:

trap '' SIGINT

Что это. Это задерживает сигнал sigint и предотвращает прерывание программы msys bash от вашей программы "снаружи". Тем не менее, он каким-то образом доставляет сигнал SIGINT до вашей программы, позволяя ему делать изящную очистку/выключение. Я не могу точно сказать, почему он работает таким образом, но он делает - по крайней мере для меня.

Удачи!

Ответ 2

Arg - 5 минут редактирования комментария. Вот что я хотел написать:

В качестве обходного пути вместо попытки захватить событие CTRL-C, которое также распространяется на оболочку, я предлагаю отключить ENABLED_PROCESSED_INPUT на stdin, чтобы CTRL-C был указан как ввод с клавиатуры, а не как сигнал:

DWORD mode;
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hstdin, &mode);
SetConsoleMode(hstdin, mode & ~ENABLE_PROCESSED_INPUT); /* disable CTRL-C processing as a signal */

Затем вы можете обрабатывать ввод с клавиатуры в своем основном потоке, в то время как остальная часть программы выполняет свою работу в отдельном потоке и устанавливает событие для очистки при получении CTRL-C.

Ответ 3

Когда вы запускаете свою программу с помощью MSYS bash, вы запускаете исполняемый файл напрямую, или есть оболочка оболочки (bash) script?

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

Если нет зарегистрированного trap или нет оболочки script, подумайте о создании такого script и добавьте свою собственную ловушку, чтобы переопределить поведение по умолчанию. Вы можете увидеть пример использования здесь или на bash man page (в разделе SHELL BUILTINS).

Ответ 4

Ctrl-C - это SIGINT? Я думал, что Ctrl-Z - это SIGINT, но Ctrl-C - SIGTERM. Проверьте это.

Ответ 5

У вас есть настройка среды CYGWIN (в переменных панели управления/среды)? Попробуйте установить CYGWIN = notty и перезапустите открытую оболочку MSYS bash - проблема сохраняется?