Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python forked processes won't die

Tags:

python

I've seen several questions like this one, but after trying various variants of checking if the children are alive and exiting the children processes, I simplified the problem and still it will not work.

Am I wrong in exiting a forked process with sys.exit(0)? Is there another way to kill it. The thing is, I cannot have the parent kill the processes since it won't know when they're done working.

At first I thought it was because a executed a system command before exiting (Python run system command and then exit... won't exit), but I've even removed that in the simplified version as given solution didn't work either.

Here's an example:

import sys
import os
import time

children = []

for i in range(0,3):    
    pid = os.fork()

    if pid == -1:
        continue
    elif pid == 0:
        # Do work...
        print 'Child %d spawned' % os.getpid()
        sys.exit(0)     
    else:
        children.append(pid)

time.sleep(5)
for pid in children:
    proc_path = '/proc/%d' % pid
    if not os.path.exists(proc_path):
        print 'Child %d is dead' % pid
    else:
        print 'Child %d is alive' % pid

This prints:

Child 27636 spawned
Child 27637 spawned
Child 27638 spawned
Child 27636 is alive
Child 27637 is alive
Child 27638 is alive

But child processes should be dead.

What causes these processes to become zombies in this case?

like image 830
JayLev Avatar asked Nov 20 '25 03:11

JayLev


2 Answers

You have to wait() for the child-process.

Please add the following lines to get things corrected:

import sys
import os
import time

children = []

for i in range(0,3):    
    pid = os.fork()

    if pid == -1:
        continue
    elif pid == 0:
        # Do work...
        print 'Child %d spawned' % os.getpid()
        sys.exit(0)     
    else:
        children.append(pid)

time.sleep(5)

# ADD NEXT TWO LINES:
for pid in children:
    os.waitpid(pid, 0)

for pid in children:
    proc_path = '/proc/%d' % pid
    if not os.path.exists(proc_path):
        print 'Child %d is dead' % pid
    else:
        print 'Child %d is alive' % pid

The parent must wait() for the child. Please see man 2 waitfor details.

In python you can handle those things with the subprocess module.

like image 155
Andreas Florath Avatar answered Nov 21 '25 17:11

Andreas Florath


For child to disappear from PID table you need wait() on parent's side.

n_still_children_alive = len(children)
while n_still_children_alive > 0:
    pid, status = os.wait()
    print "Child %d died and joined" % pid
    n_still_children_alive -= 1

If you want to play around with multiprocessing in Python, you're much better of using multiprocessing module instead of using os module.

like image 42
vartec Avatar answered Nov 21 '25 17:11

vartec



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!