2015-04-24 2 views
3

Я разрабатываю приложение Ruby on Rails. Часть функциональности - это запуск и закрытие соединения с ведомым устройством Modbus через последовательный порт, получение данных и их хранение в базе данных. Также я создал скрипт на python, который делает именно то, что мне нужно, поэтому я не хочу изобретать колесо и переписывать его в Ruby.Запуск процесса и его уничтожение из приложения Ruby on Rails без ухода из процесса зомби

Моя идея - начать процесс, который выполнит скрипт python и убьет процесс, когда он больше не понадобится.

Я начинаю процесс следующим образом, так что я могу получить доступ к его PID:

def start 
    ... 
    @@pids[ object.id ] = IO.popen("python ./python_script_name.py").pid 
    ... 

@@ ИДП является хэш, который хранит все началось ИДП-процессов с ключом, как object.id (презумпция является то, что каждый объект может начать только один процесс)

Когда я хочу, чтобы закрыть соединение я убить процесс, как:

def stop 
    ... 
    pid = @@pids[ object.id ] 
    system("kill #{pid}") 

Это приводит к процессу зомби (видимый после ps aux | grep python):

[python] <defunct> 

Я попытался отправить SIGCHLD сигнал на рельсы приложения (как родитель ранее называемый питон скрипт), но он не работает.

Я хочу добавить, что мне может потребоваться вызвать/убить этот процесс довольно часто, чтобы он мог привести к огромному количеству процессов зомби.

Как я могу убить процесс, не покидая процесс зомби?

+0

ваш скрипт python плохо реагирует на TERM. попробуйте отправить его KILL? – iced

+0

Я пробовал как «SIGKILL», так и «SIGTERM» - тот же результат. –

+1

обеспечивают некоторый воспроизводимый пример, поскольку он «работает для меня как ожидалось» с минимальным скриптом python w/sys.stdin.readline() внутри. – iced

ответ

1

Проблема не в скрипте python - сигналы обрабатываются по умолчанию (без изменений после реализации модуля signal).

Проблема в скрипте ruby. После убийства процесса его родительский сервер (сервер в этом случае) должен каким-то образом знать, что он был убит. Для этого есть функция wait. Из рубинового документации:

Родительский процесс должен использовать Process.wait для сбора статус завершения своего ребенка

Так, чтобы правильно обработать убийство дочернего процесса один должен следовать:

def stop 
    ... 
    pid = @@pids[ object.id ] 
    Process.kill(15, pid) 
    Process.wait(pid) 
    ... 
Смежные вопросы