Singleton process

F

Fortepianissimo

Here is the situation: I have multiple processes of same Python script
fired, but I want *only one* of them to continue and all the others to
quit immediately.

I can use a lock file, and the first process will get the necessary
lock. But if I do open(lockfile) all the other subsequent processes
will just wait there - instead I want them to quit immediately.

Can someone give a simple outline of how to achieve this? Thanks a
lot.
 
J

Jp Calderone

Here is the situation: I have multiple processes of same Python script
fired, but I want *only one* of them to continue and all the others to
quit immediately.

I can use a lock file, and the first process will get the necessary
lock. But if I do open(lockfile) all the other subsequent processes
will just wait there - instead I want them to quit immediately.

Can someone give a simple outline of how to achieve this? Thanks a
lot.

import os, errno

def shouldRun():
try:
os.mkdir(MAGIC_PATH)
except OSError, e:
if e.args[0] == errno.EEXIST:
return False
raise
return True

Jp

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)

iD8DBQE/5oWRedcO2BJA+4YRAtMLAJ4gbD/7v5u0+pBsETSB99FcEDHKwwCfUdtP
hXNROweDrmZMPGQRJZ7Gj94=
=JINs
-----END PGP SIGNATURE-----
 
B

Benjamin Han

But this solution creates a file race condition?

Also I just realized that lock (via fcntl.lockf() ) is actually not useful
since in this case scripts will come and go - locks will be lost whenever
a process terminates.

There should a code pattern for this - any more ideas? Thanks!

Here is the situation: I have multiple processes of same Python script
fired, but I want *only one* of them to continue and all the others to
quit immediately.

I can use a lock file, and the first process will get the necessary
lock. But if I do open(lockfile) all the other subsequent processes
will just wait there - instead I want them to quit immediately.

Can someone give a simple outline of how to achieve this? Thanks a
lot.

import os, errno

def shouldRun():
try:
os.mkdir(MAGIC_PATH)
except OSError, e:
if e.args[0] == errno.EEXIST:
return False
raise
return True

Jp
 
F

Francis Avila

Fortepianissimo wrote in message ...
Here is the situation: I have multiple processes of same Python script
fired, but I want *only one* of them to continue and all the others to
quit immediately.

I can use a lock file, and the first process will get the necessary
lock. But if I do open(lockfile) all the other subsequent processes
will just wait there - instead I want them to quit immediately.

Can someone give a simple outline of how to achieve this? Thanks a
lot.

This seems like a very strange requirement. May I ask why you're doing
this?

Anyway, if you're using a lock file, how is 'open' going to help you? Open
opens a file, creating it if it does not exist. Think about how a lockfile
would work in your situation:

- If the lockfile exists, terminate myself.
- Otherwise, create the file (thus grabbing the lock).
- Make sure somebody deletes the file when done.

Do the first with os.access('filename', os.F_OK)
Do the second with file('filename').close(). (or use os.open if you are
worried about being atomic.)
Do the third with os.unlink('filename'), if the Python process is supposed
to clean up after itself. You might want to put this into the exit signal
handler.
 
A

Andrew Bennetts

[Please don't top-post]

import os, errno

def shouldRun():
try:
os.mkdir(MAGIC_PATH)
except OSError, e:
if e.args[0] == errno.EEXIST:
return False
raise
return True

But this solution creates a file race condition?

How? mkdir is atomic. Either it creates the directory and succeeds, or it
fails. I don't see any problems here.

-Andrew.
 
B

Benjamin Han

import os, errno

def shouldRun():
try:
os.mkdir(MAGIC_PATH)
except OSError, e:
if e.args[0] == errno.EEXIST:
return False
raise
return True

But this solution creates a file race condition?

How? mkdir is atomic. Either it creates the directory and succeeds, or it
fails. I don't see any problems here.

ok I see. The reason I'm thinking of using a lock file through fcntl is that
even if a lock file exists (maybe due to a crash of some sort before), using
the locking mechanism would still work. The "test if it exists" approach
would fail because of some leftover from some accidental 'death' of the process
before.

Any more suggestion? Thanks.
 
A

Andrew Bennetts

ok I see. The reason I'm thinking of using a lock file through fcntl is that
even if a lock file exists (maybe due to a crash of some sort before), using
the locking mechanism would still work. The "test if it exists" approach
would fail because of some leftover from some accidental 'death' of the process
before.

This is a potential problem, but Python is much less prone to unhandled
crashes than C code. Use of a try/finally block, e.g.:

if shouldRun():
try:
main()
finally:
os.rmdir(MAGIC_PATH)

You could possibly use an atexit handler instead.

-Andrew.
 
C

Cameron Laird

On Mon, 22 Dec 2003, Jp Calderone wrote: [...]
import os, errno

def shouldRun():
try:
os.mkdir(MAGIC_PATH)
except OSError, e:
if e.args[0] == errno.EEXIST:
return False
raise
return True

But this solution creates a file race condition?

How? mkdir is atomic. Either it creates the directory and succeeds, or it
fails. I don't see any problems here.

ok I see. The reason I'm thinking of using a lock file through fcntl is that
even if a lock file exists (maybe due to a crash of some sort before), using
the locking mechanism would still work. The "test if it exists" approach
would fail because of some leftover from some accidental 'death' of the process
before.

Any more suggestion? Thanks.


Open a socket service. I expected Andrew to write that.

Here's how I think about this: what does the OS itself manage
as a process-referring singleton? Socket service! Only one
server can be on a port at a time; that's exactly the expressed
requirement.

Apparently I haven't needed this yet in Python. If you're will-
ing to read along in a foreign language, though, <URL: http://
wiki.tcl.tk/singleton > comments on Tcl-based implementations.
 
A

Andrew Bennetts

Open a socket service. I expected Andrew to write that.

mkdir has the advantage of being fairly simple, although it does feel a bit
hackish, because that's not what directories are meant to be used for.

Slightly cleaner would be to use os.open with the O_CREAT and O_EXCL flags,
I think. I'm not sure what the portability of those flags is, though --
whereas creating directories is supported on most platforms I can think of
:)
Here's how I think about this: what does the OS itself manage
as a process-referring singleton? Socket service! Only one
server can be on a port at a time; that's exactly the expressed
requirement.

Sure, but the OS also ensures that only one file/directory can be at a
particular path at any given time, so that's fine too. Sockets do have the
advantage of being automatically cleaned up when the process exits -- sort
of. SO_REUSEADDR is probably good enough to get the behaviour you'd want,
though.

-Andrew.
 
C

Cameron Laird

.
.
.
mkdir has the advantage of being fairly simple, although it does feel a bit
hackish, because that's not what directories are meant to be used for.

Slightly cleaner would be to use os.open with the O_CREAT and O_EXCL flags,
I think. I'm not sure what the portability of those flags is, though --
whereas creating directories is supported on most platforms I can think of
:)


Sure, but the OS also ensures that only one file/directory can be at a
particular path at any given time, so that's fine too. Sockets do have the
advantage of being automatically cleaned up when the process exits -- sort
of. SO_REUSEADDR is probably good enough to get the behaviour you'd want,
though.
.
.
.
Right: OSs certainly handle filesystems, but there's no
"cleanup", as with sockets. Also, while O_EXCL and friends
are supposed to be portable, there are a lot of subtleties
to them--and even outright errors, when NFS is involved.
 

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