Как вы справляетесь с очисткой, когда программа получает сигнал уничтожения?
Например, есть приложение, к которому я подключаюсь, которое хочет, чтобы какое-либо стороннее приложение (мое приложение) отправляло finish
команду при выходе из системы. Что лучше всего сказать, чтобы отправить эту finish
команду, когда мое приложение было уничтожено с помощью kill -9
?
редактировать 1: kill -9 не может быть захвачен. Спасибо, ребята, что поправили меня.
изменить 2: я думаю, этот случай будет, когда один вызывает просто kill, что совпадает с ctrl-c
kill -9
означает для меня: «Уходи, гнусный процесс, прочь с собой!», после чего процесс прекратит свое существование. Немедленно.kill
не то же самое, что Ctrl-C, посколькуkill
без указания того, какой сигнал отправлять, будет отправляться SIGTERM, тогда как Ctrl-C отправляет SIGINT.Ответы:
Это невозможно для любой программы, на любом языке, обрабатывать SIGKILL. Это значит, что всегда можно завершить программу, даже если она содержит ошибки или вредоносна. Но SIGKILL - не единственное средство для завершения программы. Другой - использовать SIGTERM. Программы могут обрабатывать этот сигнал. Программа должна обрабатывать сигнал, выполняя контролируемое, но быстрое завершение работы. Когда компьютер выключается, последний этап процесса выключения отправляет каждому оставшемуся процессу сигнал SIGTERM, дает этим процессам отсрочку в несколько секунд, а затем отправляет им сигнал SIGKILL.
Способ справиться с этим что - нибудь другое , чем
kill -9
было бы зарегистрировать выключение крючок. Если вы можете использовать ( SIGTERM ),kill -15
ловушка выключения будет работать. ( SIGINT )kill -2
ДЕЙСТВИТЕЛЬНО заставляет программу корректно завершиться и запустить обработчики завершения работы.Я попробовал следующую тестовую программу на OSX 10.6.3, но
kill -9
она НЕ запустила ловушку выключения, как ожидалось. Наkill -15
нем каждый раз ДЕЙСТВИТЕЛЬНО запускается ловушка выключения.Нет никакого способа действительно изящно обработать a
kill -9
в любой программе.Единственный реальный вариант для обработки a
kill -9
- это поручить другой программе-наблюдателю следить за тем, чтобы ваша основная программа ушла, или использовать сценарий-оболочку. Вы можете сделать это с помощью сценария оболочки, который опрашивалps
команду, ищущую вашу программу в списке, и действовал соответствующим образом, когда она исчезла.источник
Там являются способы обработки собственных сигналов в определенных виртуальных машинах - см этой статьи о HotSpot JVM , например.
Используя внутренний
sun.misc.Signal.handle(Signal, SignalHandler)
вызов метода Sun, вы также можете зарегистрировать обработчик сигнала, но, вероятно, не для сигналов, подобныхINT
илиTERM
используемых JVM.Чтобы иметь возможность обрабатывать любой сигнал, вам придется выпрыгнуть из JVM на территорию операционной системы.
Что я обычно делаю (например), чтобы обнаружить ненормальное завершение, - это запустить мою JVM внутри сценария Perl, но заставить сценарий ждать JVM с помощью
waitpid
системного вызова.Затем я получаю информацию о выходе из JVM и о причинах выхода и могу предпринять необходимые действия.
источник
INT
иTERM
сsun.misc.Signal
, но вы не можете обрабатывать,QUIT
потому что JVM резервирует его для отладки, а такжеKILL
потому, что ОС немедленно завершит JVM. Попытка справиться с любым из них приведет к возникновениюIllegalArgumentException
.Я ожидал, что JVM корректно прервет (
thread.interrupt()
) все запущенные потоки, созданные приложением, по крайней мере, для сигналовSIGINT (kill -2)
иSIGTERM (kill -15)
.Таким образом, сигнал будет переадресован им, что позволит изящно отменить поток и завершить ресурс стандартными способами .
Но это не так (по крайней мере , в моей реализации JVM:
Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
.Как отмечали другие пользователи, использование хуков выключения кажется обязательным.
Итак, как мне с этим справиться?
Ну, во-первых, меня это не волнует во всех программах, только в тех, где я хочу отслеживать отмены пользователей и неожиданные окончания. Например, представьте, что ваша java-программа - это процесс, которым управляет другой. Возможно, вы захотите различить, было ли оно корректно завершено (
SIGTERM
из процесса менеджера) или произошло завершение работы (чтобы автоматически перезапустить задание при запуске).Как правило, я всегда заставляю свои долго работающие потоки периодически узнавать о состоянии прерывания и бросать,
InterruptedException
если они прерваны. Это позволяет завершить выполнение способом, контролируемым разработчиком (что также дает тот же результат, что и стандартные операции блокировки). ЗатемInterruptedException
захватывается верхний уровень стека потоков и выполняется соответствующая очистка. Эти потоки закодированы, чтобы знать, как отвечать на запрос прерывания. Конструкция с высокой степенью сцепления .Итак, в этих случаях я добавляю ловушку выключения, которая делает то, что, по моему мнению, JVM должна делать по умолчанию: прерывает все не-демонические потоки, созданные моим приложением, которые все еще работают:
Заполните тестовое приложение на github: https://github.com/idelvall/kill-test
источник
Можно использовать
Runtime.getRuntime().addShutdownHook(...)
, но нельзя гарантировать, что он будет вызван в любом случае .источник
Есть один способ отреагировать на kill -9: создать отдельный процесс, который следит за убиваемым процессом и при необходимости очищает его после него. Это, вероятно, будет связано с IPC и потребует довольно много работы, и вы все равно можете переопределить его, убив оба процесса одновременно. Я полагаю, что в большинстве случаев это не стоит того.
Тот, кто убивает процесс с помощью -9, теоретически должен знать, что он / она делает, и что это может привести к несогласованному состоянию.
источник