[2.4.2/Linux] Getting Python to fork?

G

Gilles Ganault

Hello

I need to launch a Python script, and fork it so that the calling
script can resume with the next step will the Python script keeps
running.

I tried those two, but they don't work, as the calling script is stuck
until the Python script ends:

sys.stdout = open(os.devnull, 'w')

=====
#if os.fork():
pid = os.fork()
if pid > 0:
sys.exit(0)
=====

Should I use another library to do this?

Thank you.
 
G

Gary Herron

Gilles said:
Hello

I need to launch a Python script, and fork it so that the calling
script can resume with the next step will the Python script keeps
running.

I tried those two, but they don't work, as the calling script is stuck
until the Python script ends:

sys.stdout = open(os.devnull, 'w')

=====
#if os.fork():
pid = os.fork()
if pid > 0:
sys.exit(0)
=====

Should I use another library to do this?

Thank you.
What OS? Stuck how? I you want both processes to execute, why do you
call sys.exit? I don't think you've shown enough code to tell what you
are doing right or wrong. Try this:

pid = os.fork()
if pid:
# Original fork continues here
# pid is child's process id
# ... so onwards with the next step
# If it needs to wait for the child to complete, it can call os.waitpid
else:
# New fork continues here, independently of the original process
# doing whatever the fork was create for

Gary Herron
 
J

Jon Ribbens

I need to launch a Python script, and fork it so that the calling
script can resume with the next step will the Python script keeps
running.

I tried those two, but they don't work, as the calling script is stuck
until the Python script ends:

This should work I believe:

if os.fork():
os._exit(0)
os.setsid()
os.chdir("/")
fd = os.open("/dev/null", os.O_RDWR)
os.dup2(fd, 0)
os.dup2(fd, 1)
os.dup2(fd, 2)
if fd > 2:
os.close(fd)
# do stuff

Although bear in mind it's pretty UNIX-y.
 
C

Christian Heimes

Jon said:
This should work I believe:

if os.fork():
os._exit(0)
os.setsid()
os.chdir("/")
fd = os.open("/dev/null", os.O_RDWR)
os.dup2(fd, 0)
os.dup2(fd, 1)
os.dup2(fd, 2)
if fd > 2:
os.close(fd)
# do stuff

Although bear in mind it's pretty UNIX-y.

IIRC you have to fork a second time after you have changed the working
dir and created a new session group.

Christian
 
J

Jon Ribbens

IIRC you have to fork a second time after you have changed the working
dir and created a new session group.

Why? I don't think you do.
Neither does BSD daemon.c or glibc daemon.c
 
B

Bernard

Hello

I need to launch a Python script, and fork it so that the calling
script can resume with the next step will the Python script keeps
running.

I tried those two, but they don't work, as the calling script is stuck
until the Python script ends:

sys.stdout = open(os.devnull, 'w')

=====
#if os.fork():
pid = os.fork()
if pid > 0:
sys.exit(0)
=====

Should I use another library to do this?

Thank you.

this works out for me:

def tryToFork(cbk, fork=True):
'''
If possible, start the process as a daemon under linux
otherwise start it normally under Windows

the 'fork' flag may deactivate the forking if it is set to False
'''

#UNIX/LINUX: FORK
if fork:
try:
#Fork and commit suicide
if os.fork():
sys.exit(0)

#What to do in parent process
else:
os.setsid()
sys.stdin = open('/dev/null')
sys.stdout = open('/dev/null', 'w')
sys.stderr = open('/dev/null', 'w')
cbk()

#WINDOWS: JUST RUN
except AttributeError:
cbk()

#PLAIN, NORMAL RUN
else:
cbk()

def whateverFunctionToFork():
pass
tryToFork(whateverFunctionToFork, True)
 
J

Jon Ribbens

#Fork and commit suicide
if os.fork():
sys.exit(0)

I'm pretty sure that should be os._exit(0)
#What to do in parent process

This is now the child process.
sys.stdin = open('/dev/null')
sys.stdout = open('/dev/null', 'w')
sys.stderr = open('/dev/null', 'w')

I think that's changing Python's idea of stdin etc but not the
operating system's idea of them. You won't be closing the original
file descriptors, and if you run any subprocesses they will end up
with the original stdin/out/err. Unless sys.stdin is more magic
than I'm aware of.
 
C

Christian Heimes

Jon said:
I think that's changing Python's idea of stdin etc but not the
operating system's idea of them. You won't be closing the original
file descriptors, and if you run any subprocesses they will end up
with the original stdin/out/err. Unless sys.stdin is more magic
than I'm aware of.

Jon is correct here. You must close or redirect the underlying C file
descriptor. Python's sys.std streams don't magically do this for you
because Python keeps a backup of the standard streams for internal
purpose in sys.__std*__. os.dup2 is the best solution.

Christian
 
C

Christian Heimes

Jon said:
Why? I don't think you do.
Neither does BSD daemon.c or glibc daemon.c

The problem is well documented at
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012

"""
The second fork _is_ necessary, Jonathan Bartlett, 2003/10/31
The first fork accomplishes two things - allow the shell to return, and
allow you to do a setsid().

The setsid() removes yourself from your controlling terminal. You see,
before, you were still listed as a job of your previous process, and
therefore the user might accidentally send you a signal. setsid() gives
you a new session, and removes the existing controlling terminal.

The problem is, you are now a session leader. As a session leader, if
you open a file descriptor that is a terminal, it will become your
controlling terminal (oops!). Therefore, the second fork makes you NOT
be a session leader. Only session leaders can acquire a controlling
terminal, so you can open up any file you wish without worrying that it
will make you a controlling terminal.

So - first fork - allow shell to return, and permit you to call setsid()

Second fork - prevent you from accidentally reacquiring a controlling
terminal.
"""
 
J

Jon Ribbens

To create a deamon, you indeed need to fork two times. For more
information and a working example see:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731 . I'm
quite sure this works, because I used it several times to create a deamon.

That doesn't mean it works. That just means it hasn't failed while
you were watching.

(Not that I am saying it's necessarily wrong, I'm just saying that
"it worked when I tried it" is a very bad way of deciding if something
is correct code.)
 
G

Gilles Ganault

To create a deamon, you indeed need to fork two times.

Do I really need this much complication just to exit the script and
let a child handle the pop-up?

I've changed this line, and the parent still doesn't return, and the
script waits until the child ends before resuming to the next step:

if os.fork():
#BAD? sys.exit(0)
os._exit(0)
else:

Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top