server bootstrapping upon connection (WARNING: LONG)
ralf at brainbot.com
ralf at brainbot.com
Tue Feb 10 18:22:30 EST 2004
Benjamin Han <this at is.for.spambot> writes:
> On 2004-02-10 13:46:37 -0500, ralf at brainbot.com said:
>
>> fortepianissimo at yahoo.com.tw (Fortepianissimo) writes:
>>> The problem: I need to prevent multiple copies of the server being
>>> started. I did this by using file locking (fcntl.lockf()). However,
>>> not every time the code successfully prevented the server being
>>> started up more than one time. Here is the relevant code:
>> When using fcntl.lockf different FooClient instances in the same
>> process will be able lock the file and start another server. You could
>> either use fcntl.flock to prevent that or use some global flag.
>
> Hm... I didn't know there's a difference between flock() and lockf(),
> and I didn't get much info from the document either. Could you explain
> a bit on why lockf() would not lock the file?
Well, it might lock the file multiple times in the same
process. That's the problem:
----
import fcntl
def getlockfile():
return open('serverStart.lock', 'w')
def getlock(f):
try:
lock(f.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
except:
return False
return True
def doit():
f1 = getlockfile()
f2 = getlockfile()
print getlock(f1), getlock(f2)
lock = fcntl.lockf
doit()
lock = fcntl.flock
doit()
---
Output is:
True True
True False
>
> Actually I wrote a tiny script just to test if lockf() does what it
> claims to do:
>
> --- CODE STARTS ---
> #!/usr/bin/env python
>
> import os,fcntl,sys
>
> print "* about to open flock.txt"
> f=open('flock.txt','w')
> print "* opened the file"
> fcntl.lockf(f.fileno(),fcntl.LOCK_EX|fcntl.LOCK_NB)
> print "* obtained the lock, enter your line below:"
> l=sys.stdin.readline()
> f.truncate()
> f.write(l)
> f.flush()
> sys.stdin.readline()
> f.close()
>
> --- CODE ENDS ---
>
> It seems it does lock the file? (Mac OS X 10.3.2).
>
>> Also be sure to keep the file open by keeping a reference to it
>> (i.e. self.serverStartLock=open(...)). For debugging purposes,
>> remove that 'if self.connect(): return' and
>> I think you'll see much more servers being started.
>
> --- CODE SNIPPET STARTS ---
> class FooClient:
> def __init__ (self, startServer=True):
> """Connects to FooServer if it exists, otherwise starts it and
> connects to it"""
> self.connected=True
> if self.connect(): return
> elif not startServer:
> if FOO_CLIENT_DEBUG: log('connection failed 1')
> self.connected=False
> return
> ..
> --- CODE SNIPPET ENDS ---
>
> Well in that case every connection will try to start a server. Good
> point on keeping a reference to the lock file though - I'll add to it
> and see what happens.
>
>>> From the log (when problem occurred) I see even *AFTER* the server
>>> was
>>> started and accepted connections (several connections came and went
>>> happily), a connection would come in and hit the "connection failed 1"
>>> log line. This shouldn't have happened as the default value of
>>> startServer for FooClient.__init__() is True. In the very same
>> Well, maybe too many connection attempts are pending...
>
> I failed to see why this should affect the default value of the
> argument... if startServer is True (default), that log line should
> have never been reached.
Well, then I suppose you're passing an false argument to
FooClient.__init__. I just wanted to say, that even if the server is
listening on that port, that connection attempts may fail.
>
> Thanks!
>
> Ben
--
brainbot technologies ag
boppstrasse 64 . 55118 mainz . germany
fon +49 6131 211639-1 . fax +49 6131 211639-2
http://brainbot.com/ mailto:ralf at brainbot.com
More information about the Python-list
mailing list