Я запускаю его с помощью psutil.Popen() и оставляю его работать на две секунды. Если он не завершается естественным образом, я отправляю SIGKILL ему и всем его возможным дочерним элементам.
Проблема в том, что если я уничтожу один скрипт из-за сверхурочного выполнения и запущу другой, основной (Python) скрипт получит SIGSTOP.
На моей локальной машине я принял действительно глупое решение: скрипт Python записал свой PID в файл при запуске, а затем я запускаю другой скрипт, который отправлял SIGCONT каждую секунду к PID, который был сохранен в файле.
Это имеет две проблемы: это действительно глупо, но еще хуже то, что он отказывается работать на сервере. SIGCONT там просто ничего не делает.
Последовательность такова: сценарий Python запускает сценарий Bash, реагирующий на тюрьму, и этот сценарий Bash запускает потенциально опасный и/или бесконечный сценарий. У этого сценария также могут быть дочерние элементы.
Соответствующие части кода:
Основной сценарий Python
Код: Выделить всё
p = psutil.Popen(["bash", mode, script_path, self.TESTENV_ROOT])
start = time.time()
while True:
if p.status() == psutil.STATUS_ZOMBIE:
# process ended naturally
duration = time.time() - start
self.stdout.write("Script finished, execution time: {}s".format(duration))
break
if time.time() > start + run_limit:
children = p.children(recursive=True)
for child in children:
child.kill()
p.kill()
duration = None
self.stdout.write("Script exceeded maximum time ({}s) and was killed.".format(run_limit))
break
time.sleep(0.01)
os.kill(os.getpid(), 17) # SIGCHLD
return duration
Код: Выделить всё
#!/usr/bin/env bash
# Copy the script to the chroot environment
cp "$1" "$2/prepare.sh"
# Run the script
chmod u+x "$2/prepare.sh"
echo './prepare.sh' | chroot "$2"
rm "$2/prepare.sh"
Код: Выделить всё
#!/bin/bash
echo asdf > file
Код: Выделить всё
import psutil
import os
import time
while True:
if os.path.exists("infinite.sh"):
p = psutil.Popen(["bash","infinite.sh"])
start = time.time()
while True:
if p.status() == psutil.STATUS_ZOMBIE:
# The process ended naturally
break
if time.time() > start + 2:
# The process needs too much time and has to be killed
children = p.children(recursive=True)
for child in children:
child.kill()
p.kill()
break
os.remove("infinite.sh")
os.kill(os.getpid(), 17)
- Почему я получаю сообщения SIGSTOP? Это из-за тюрьмы chroot?
- Есть ли лучший способ решить мою проблему, чем запустить сценарий «пробуждения»?
РЕДАКТИРОВАТЬ 2: Я провел еще больше исследований, и критической строкой является echo './prepare.sh' | chroot "$2" в сценарии Bash, управляющем тюрьмой chroot. Теперь вопрос в том, что, черт возьми, с этим не так?
РЕДАКТИРОВАТЬ 3: Это может быть связанной проблемой, если это кому-то поможет.