Предотвращение MSYS 'bash' от процессов убийства, которые ловят ^C
у меня есть консольное приложение Windows (портированное из Unix), которое изначально было разработано для чистого выхода при получении ^C (Unix SIGINT
). Чистый выход в этом случае предполагает ожидание, потенциально довольно долгое время, закрытия удаленных сетевых подключений. (Я знаю, что это не нормальное поведение ^C но я не в состоянии изменить его.) Программа однопоточная.
Я могу поймать ^C С signal(SIGINT)
(как в UNIX) или с SetConsoleCtrlHandler
. Либо работает правильно, когда программа запускается под CMD.ИСПОЛНЯЕМЫЙ. Однако, если я использую оболочку "bash", которая поставляется с MSYS (я использую среду MinGW для создания программы, так как это позволяет мне повторно использовать файлы Makefile Unix), то программа принудительно завершается некоторое случайное короткое время (менее 100 миллисекунд) после ^C. Это неприемлемо, так как, как я уже упоминал, программа должна ждать удаленной сети соединения для закрытия.
очень вероятно, что люди захотят запустить эту программу под MSYS bash. Кроме того, этот эффект нарушает тестов. Я не смог найти способ обойти проблему ни из программы (идеально), ни по настройкам на оболочке (приемлемо). Кто-нибудь может что-нибудь порекомендовать?
6 ответов
Это может быть связано с печально известным 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 .
У меня была точно такая же проблема - я написал программу с обработчиком SIGINT/SIGTERM. Этот обработчик делал уборку, которая иногда занимала некоторое время. Когда я запускал программу из msys bash, ctrl - c вызывал запуск моего обработчика SIGINT, но он не заканчивался-программа была завершена ("извне", как это было), прежде чем она могла завершить свою очистку.
основываясь на ответе phs, и этот ответ на аналогичный вопрос: https://stackoverflow.com/a/23678996/2494650, я придумал следующее решение. Это безумно просто, и это может иметь некоторые побочные эффекты, которые я еще не обнаружил, но это исправило проблему для меня.
создайте файл ~/.файл bashrc следующую строку:
trap '' SIGINT
вот и все. Это ловушки сигнала sigint и предотвращает msys bash от завершения вашей программы "извне". Тем не менее, он каким-то образом все еще позволяет сигналу SIGINT до вашего программа, позволяющая ей выполнять изящную очистку / выключение. Я не могу точно сказать, почему это так работает, но это так - по крайней мере для меня.
удачи!
Arg-5 минут редактирования по комментарию. Вот что я хотел написать:--2-->
в качестве обходного пути, вместо того, чтобы пытаться поймать событие 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.
когда вы запускаете свою программу с MSYS bash, вы запускаете исполняемый файл напрямую или есть сценарий оболочки обертывания (bash)?
Если это так, он может регистрировать пользовательский обработчик Ctrl-C с trap
command (это делает сон с последующим убийством.) Если такая вещь существует, измените или удалите ее.
Если нет trap
registered, или нет сценария обертывания, рассмотрите возможность создания такого сценария и добавления собственной ловушки для переопределения поведения по умолчанию. Вы можете см. пример того, как его использовать здесь или man page Баша (в разделе оболочки BUILTINS).
У вас есть настройка среды CYGWIN (в панели управления/переменных среды)? Попробуйте установить CYGWIN=notty и перезапустить новую оболочку MSYS bash-проблема сохраняется?