Каковы причины появления SIGSTOP в Linux и как с этим справиться?Python

Программы на Python
Anonymous
Каковы причины появления SIGSTOP в Linux и как с этим справиться?

Сообщение Anonymous »

У меня есть сценарий Python, который запускает сценарии Bash. Мне нужно иметь возможность завершить сценарий Bash, если он кажется бесконечным, а также его нужно запускать в тюрьме chroot, потому что сценарий может быть опасным.
Я запускаю его с помощью 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
Запуск сценария в chroot ($1 — это сценарий, который будет запускаться в chroot-тюрьме, а $2 — путь к тюрьме)

Код: Выделить всё

#!/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"
Пример сценария подготовить.sh

Код: Выделить всё

#!/bin/bash
echo asdf > file
Я потратил некоторое время, пытаясь решить эту проблему. Я обнаружил, что этот скрипт (который не использует тюрьму chroot для запуска скриптов Bash) работает отлично:

Код: Выделить всё

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?
  • Есть ли лучший способ решить мою проблему, чем запустить сценарий «пробуждения»?
РЕДАКТИРОВАТЬ: Я обнаружил, что сигнал остановлен в момент запуска первого сценария после того, как я убил сверхурочный. Неважно, использую ли я os.system или psutil.Popen.
РЕДАКТИРОВАТЬ 2: Я провел еще больше исследований, и критической строкой является echo './prepare.sh' | chroot "$2" в сценарии Bash, управляющем тюрьмой chroot. Теперь вопрос в том, что, черт возьми, с этим не так?
РЕДАКТИРОВАТЬ 3: Это может быть связанной проблемой, если это кому-то поможет.

Вернуться в «Python»