Зависание родительского процесса после запуска тайм-аута подпроцесса и результатов конвейеризации - PullRequest
1 голос
/ 02 июля 2019

Я написал некоторый код для запуска сценария (через подпроцесс) и уничтожения дочернего процесса после определенного времени ожидания. Я запускаю скрипт под названием «runtime_hang_script.sh», который просто содержит «./runtime_hang», который запускает бесконечный цикл. Я также перенаправляю stdout в канал - я планирую записать его как в sys.stdout, так и в файл (иначе я пытаюсь реализовать tee). Однако мой код зависает после истечения времени ожидания подпроцесса. Обратите внимание, что это зависает ТОЛЬКО при запуске "sh runtime_hang_script.sh", а не "./runtime_hang." Кроме того, это не зависает, когда я пытаюсь передать напрямую в файл или когда я не читаю из канала.

Я пробовал другие реализации создания временного подпроцесса, но я продолжаю сталкиваться с той же проблемой. Я даже пытался поднять сигнал в конце проблемы - по какой-то причине сигнал повышается раньше, чем ожидалось, поэтому это тоже не работает. Любая помощь будет оценена. Заранее спасибо!

process = None

def run():
    global process
    timeout_secs = 5
    args = ['sh', 'runtime_hang_script.sh']
    sys.stdout.flush()

    process = subprocess.Popen(args, stdout=subprocess.PIPE, bufsize=1)

    with process.stdout:
        for line in iter(process.stdout.readline, b''):
            sys.stdout.write(line.decode('utf-8'))
        sys.stdout.flush()

    process.wait()


proc_thread = threading.Thread(target=run)
proc_thread.start()
proc_thread.join(5)

print(proc_thread.is_alive())

if proc_thread.is_alive():
    process.kill()

1 Ответ

0 голосов
/ 02 июля 2019

Предполагая, что вы используете Python 3.3 или новее, вы можете использовать аргумент времени ожидания метода subprocess.communicate() для реализации своего 5-секундного времени ожидания:

import subprocess
import sys

timeout_secs = 5
args = ['sh', 'runtime_hang_script.sh']

process = subprocess.Popen(args, stdout=subprocess.PIPE, bufsize=1)
try:
   print("Waiting for data from child process...")
   (stdoutData, stderrData) = process.communicate(None, timeout_secs)
   print("From child process:  stdoutData=[%s] stderrData=[%s]" % (stdoutData, stderrData))
except subprocess.TimeoutExpired:
   print("Oops, child process took too long!  Now it has to die")
   process.kill()

print("Waiting for child process to exit...")
process.wait()
print("Child process exited.")

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...