Предотвращение 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. Кроме того, этот эффект нарушает набор тестов. Я не смог найти какой-либо способ обойти проблему либо изнутри программы (идеально), либо с помощью настроек на оболочке (допустимо). Кто-нибудь может что-нибудь рекомендовать?
Ответы
Ответ 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 - проблема сохраняется?