Убедитесь, что дочерние процессы будут уничтожены в случае сбоя родительского процесса в python. Решение должно поддерживать все операционные системы - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть приложение, в котором родительский процесс опрашивает сервер, чтобы получить задания на загрузку, а затем порождает дочерние процессы, чтобы завершить задание. Этот цикл продолжается до тех пор, пока родительский процесс не обработает некоторые задания. Мне нужно убедиться, что дочерние процессы d ie в случае сбоя родительского процесса. Я использую python в качестве языка программирования. Плюс, скажем, в случае смерти родительского процесса он вызывается каким-то другим процессом. Ниже приведены некоторые механизмы - 1. Согласно многопроцессорному модулю python - «Когда процесс завершается, он пытается завершить все свои дочерние процессы daemoni c». Так что он пытается, но не гарантирует. Так что это не надежно. 2. Я могу добавить запись в db с отображением child_process_id-> jobId, который сообщает, какой дочерний процесс загружает какое задание. Когда родительский процесс запускается перед опросом, он проверяет, есть ли запись child_process_id-> jobId. В случае если он убивает процесс с заданным child_process_id и отправляет jobId в следующем опросе. Могу ли я иметь чистый способ уничтожения дочерних процессов при внезапном сбое родительского процесса? Мне нужно решение, совместимое с windows, linux и ma c. Кто-то предложил мне, что блокировки файлов могут мне помочь, но я не мог понять, как блокировки файлов могут помочь мне достичь этого.

1 Ответ

0 голосов
/ 05 мая 2020
#parent.py

import time
import subprocess
import file_lock_lib
import os

PARENT_LOCK_NAME = "ParentChildTask"
CHILD_LOCK_NAME = "ChildTask-%d"


def main():

    #for running single parent process
    fmutex, res = file_lock_lib.FileLock(PARENT_LOCK_NAME, True)
    print("PARENT ID is =============" + str(os.getpid()))
    if not res:
        print("ParentProcess already running")
        exit(1)

    print("Spawing Child Processes")
    r = subprocess.Popen(["python", "/Users/abi/PycharmProjects/osProgramming/parent_child/child.py"])
    #aquire the lock for child process
    c_lock, res = file_lock_lib.FileLock(CHILD_LOCK_NAME% r.pid)

    import time
    start_time = int(time.time())
    while (int(time.time()) - start_time) < 180:
        a = 1
    1/0
    #file_lock_lib.FileUnlock(fmutex)

if __name__ == '__main__':
    main()


#file_lock.lib.py

import sys
import os

if sys.platform != 'win32':
    'NOOB_IDS fcntl sysv_ipc sendmsg'
    import fcntl




def FileLock(fname, nb=False):
    if sys.platform == 'win32':
        try:
            sa = w32s.SECURITY_ATTRIBUTES()
            sa.SetSecurityDescriptorDacl(True, None, False)
            fmutex = win32event.CreateMutex(sa, False, fname)
        except pywintypes.error as fault:
            if fault.winerror == 5:
                fmutex = win32event.OpenMutex(win32event.SYNCHRONIZE, False, fname)
            else:
                raise

        if nb:
            wtime = 0
        else:
            wtime = win32event.INFINITE

        rc = win32event.WaitForSingleObject(fmutex, wtime)
        if rc == win32event.WAIT_TIMEOUT or rc == win32event.WAIT_FAILED:
            win32api.CloseHandle(fmutex)
            return None, False
    else:
        if not fname.startswith('/'):
            # Not an absolute path name, prefix in $HOME/.inSync
            fname = os.path.join(os.getenv('HOME'), '.file_lock_lib', fname)

        fdir = os.path.dirname(fname)
        if not os.path.exists(fdir):
            os.makedirs(fdir)

        try:
            fmutex = open(fname, "rb+")
        except:
            fmutex = open(fname, "wb+")
        try:
            flags = fcntl.LOCK_EX
            if nb:
                flags |= fcntl.LOCK_NB
            fcntl.flock(fmutex.fileno(), flags)
        except IOError:
            return None, False

    return fmutex, True


def FileUnlock(fmutex):
    if sys.platform == 'win32':
        win32event.ReleaseMutex(fmutex)
        win32api.CloseHandle(fmutex)
    else:
        fcntl.flock(fmutex.fileno(), fcntl.LOCK_UN)
        fmutex.close()


#child.py

import time
import subprocess
import file_lock_lib
import os

PARENT_LOCK_NAME = "ParentChildTask"
CHILD_LOCK_NAME = "ChildTask-%d"


def main():
    print("CHILD PID  =================" + str(os.getpid()))
    #check if parent process is running
    fmutex, res = file_lock_lib.FileLock(PARENT_LOCK_NAME, True)
    if res:
        file_lock_lib.FileUnlock(fmutex)
        print("Parent process is not running")
        exit(1)

    print("Child Started")
    #spwan a thread to do work

    #wait on Parent
    mtx, res = file_lock_lib.FileLock(CHILD_LOCK_NAME%os.getpid())
    file_lock_lib.FileUnlock(mtx)
    print("Child Exited as parent process was killed")


if __name__ == '__main__':
    main()

Я нашел способ решить проблему. Рассмотрим родительский и дочерний процессы из кода выше. Надеюсь, что это решение работает ....

...