how to permanently kill zombie processes in python

Question:

The problem is as follows: there are two threads, one creates (the creator) tasks (processes), the second, under certain conditions, must kill them (the killer). To transfer information, a common dictionary dict () is used in which the creator writes processes, and the killer starts dict["PROC_TO_KILL"].terminate for the given dict["PROC_TO_KILL"].terminate

The question is the following, when this terminate function is called, the processes continue to be displayed as "zombie processes Z", how to permanently kill the process? And a sub-question: how to recursively delete all processes that were spawned by this process (or will it be done automatically)? ! Nuance: in debug mode, the code works fine, the process is killed without the appearance of "zombies".

Their options are commented out in the killer's code, they either do not work or give the same option.

Main

def Main():
    table_proc = dict()  # таблица процессов 
    lock = Lock()   

    # создание классов-потоков
    creator = Creator(... lock, table_proc)
    creator.start()  # запуск создателя

    killer = Killer(...lock, table_proc)
    killer.start()  # запуск киллера

    creator.join()  # main() ждет смерти этого потока
    killer.join()  # main() ждет смерти и этого потока


# Тестовая функция процесс порождаемый создателем
def New_Func(name):
    while True:
        print("I'm %s my PID: %i") % (name, os.getpid())
        time.sleep(2)
    print "NO MORE "


if __name__ == '__main__':
    Main()  # начало программы

In the thread creator:

def create_proc(self, body):
    p = Process(target=New_Func, args=(body["name"],))
    self.lock.acquire()
    try:
        self.table_proc[body["name"]] = p
    except Exception as inst1:
        print(inst) #обработка исключения
        self.lock.release()
        return False
        pass
    finally:  
        self.lock.release()

    p.daemon = True  
    p.start()  
    return True

In the killer:

def kill(self, body):
    self.lock.acquire()  
    try:
        self.table_proc[body["name"]].terminate()  из таблицы
        #os.kill(self.table_proc[body["name"]].pid, 9)
        #os.kill(self.table_proc[body["name"]].pid, os.SIGTERM)
        #os.killpg(os.getpgid(self.table_proc[body["name"]]), os.SIGTERM)
        #todo УДАЛИТЬ из таблицы задач
    except Exception as inst1:
        print(inst1)
        self.lock.release
        return False
        pass
    finally:
        self.lock.release()  
    return True

Answer:

The solution was found independently (with a work colleague):

The problem was that, although the process terminate() after the terminate() command, the object's resources were not completely released. Hope the solution is cross-platform and helpful to the community.

def kill(self, body):
    self.lock.acquire()  # блокировка разделяемого объекта 
    try:
        self.table_proc[body["name"]].terminate()  #остановка процесса
        self.table_proc[body["name"]].join() # ждем освобождение ресурсов ("анти-зомбарин")
        del self.table_proc[body["name"]] # убить процесс из таблицы
    except Exception as inst1:
        print(inst1)
        self.lock.release
        return False
        pass
    finally:
        self.lock.release()  # в любом случае освобождаем объект от блокировки
        pass
    return True

For an accurate check, a process factory will be made for killing and creating arbitrary tasks, with a check of the solution.

UPD: the solution has been tested, it works correctly.

Scroll to Top