Предотвращение MSY 'bash' от процессов убийства, которые ловят ^ C - PullRequest
33 голосов
/ 17 августа 2011

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

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

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

Ответы [ 6 ]

7 голосов
/ 12 августа 2015

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

Опираясь на ответ phs и ответ на аналогичный вопрос: https://stackoverflow.com/a/23678996/2494650, Я нашел следующее решение. Это безумно просто, и у него могут быть некоторые побочные эффекты, которые мне еще предстоит обнаружить, но это решило проблему для меня.

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

trap '' SIGINT

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

Удачи!

1 голос
/ 05 октября 2018

Это может быть связано с печально известной проблемой mintty «Взаимодействие ввода / вывода с инопланетными программами» (она же mintty проблема # 56 ). В этом случае это проявляется в том, что Ctrl-C внезапно убивает программу, а не передается программе как сигнал, который нужно поймать и обработать. Доказательства этой теории основаны на обширном объяснении zwol: «приложение Windows в консольном режиме», «[приложение] предназначено для чистого выхода при получении ^ C », «[приложение] работает правильно, когда программа запускается под CMD.EXE «но» [при использовании терминала], поставляемого с MSYS [...], программа принудительно завершается »(на момент написания (2018) MSYS по умолчанию использует mintty в качестве своего терминала).

К сожалению mintty не является полной заменой консоли Windows , и различные варианты поведения, ожидаемые "родными" программами Windows, не реализованы. Тем не менее, вы можете испытать радость, оборачивая такие нативные программы в winpty , когда запускаете их внутри mintty ...

Другие вопросы также описывают это поведение: см. https://superuser.com/questions/606201/how-to-politely-kill-windows-process-from-cygwin и https://superuser.com/questions/1039098/how-to-make-mintty-close-gracefully-on-ctrl-c.

1 голос
/ 07 сентября 2011

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.

0 голосов
/ 06 сентября 2011

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

0 голосов
/ 06 сентября 2011

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

0 голосов
/ 05 сентября 2011

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

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

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

...