Question: posix fcntl module
Ignacio Vazquez-Abrams
ignacio at openservices.net
Tue Aug 28 20:02:51 EDT 2001
On Tue, 28 Aug 2001, Sheila King wrote:
> On Tue, 28 Aug 2001 18:51:40 -0400 (EDT), Ignacio Vazquez-Abrams
> <ignacio at openservices.net> wrote in comp.lang.python in article
> <mailman.999039163.17806.python-list at python.org>:
>
> :>From the fcntl(2) man page:
> :
> :"
> : F_SETLK
> : The lock is set (when l_type is F_RDLCK or F_WRLCK)
> : or cleared (when it is F_UNLCK). If the lock is
> : held by someone else, this call returns -1 and sets
> : errno to EACCES or EAGAIN.
> :"
> :
> :>From <bits/fcntl.h>:
> :---
> :#define F_RDLCK 0 /* Read lock. */
> :#define F_WRLCK 1 /* Write lock. */
> :#define F_UNLCK 2 /* Remove lock. */
> :---
> :
> :Those are the values you want to use. It looks like Python may have this one
> :wrong.
>
> Well, this sounded good to me. So, I tried this:
>
> ''' posixLock.py
>
> class lockfile
> supports the same function calls as
> winLock.lockfile
> export to LockFile.py: a wrapper module
> around the win and posix lockfiles
> '''
>
> import os, fcntl
>
> class lockfile:
> def __init__(self, filename):
> if os.access(filename, os.F_OK):
> self.filename = filename
> else:
> errmssg = filename + " does not exist. Can't lock non-existent file."
> raise IOError, errmssg
>
> def getReadLock(self):
> self.f = open(self.filename)
> self.fd = self.f.fileno()
> fcntl.lockf(self.fd, fcntl.F_RDLCK)
>
> def getWriteLock(self):
> self.f = open(self.filename)
> self.fd = self.f.fileno()
> fcntl.lockf(self.fd, fcntl.F_WRLCK)
>
> def unlock(self):
> fcntl.lockf(self.fd, fcntl.F_UNLCK)
> self.f.close()
> del self.fd
>
> def flock(self, flag):
> '''flags are:
> LOCK_UN - unlock
> LOCK_SH - acquire a shared (or read) lock
> LOCK_EX - acquire an exclusive (or write) lock
> '''
> if flag == 'LOCK_SH':
> self.getReadLock()
> elif flag == 'LOCK_EX':
> self.getWriteLock()
> elif flag == 'LOCK_UN':
> self.unlock()
> else:
> errmssg = "The flag " + flag + " is not implemented for flock"
> raise NotImplementedError, errmssg
>
>
> But, in an interactive session, I got:
>
> [snip]
>
> Additional advice is welcome...
>
> --
> Sheila King
> http://www.thinkspot.net/sheila/
> http://www.k12groups.org/
Oh hell. fcntlmodule.so munges the parameter passed to it so that LOCK_UN
looks like F_UNLCK, LOCK_SH like F_RDLCK, and LOCK_EX like F_WRLCK. Whose
bright idea was that anyway?
But I think I have found the real reason this time. Passing no mode argument
to open() tells Python to open the file read-only. Guess what? By rejecting
LOCK_EX Linux is telling you "Write lock? Why the hell does a read-only file
need a write lock?". Same thing with 'w' and LOCK_SH. 'w+' and 'r+' can take
both.
So it seems that you need to take both a filename _and_ a mode in __init__(),
and then raise an exception in the appropriate locking methods based on
f.mode. You may also want to take a third parameter for initial lock mode,
just in case.
Also, you should make it so that the file is immediately opened in __init__(),
then close the file both in a close() method and in __del__(). In both methods
you should probably check f.closed to make sure that the file hasn't already
been closed.
Hopefully your problem has now been solved. Third (or fourth or whatever :) )
time's the charm, right?
--
Ignacio Vazquez-Abrams <ignacio at openservices.net>
More information about the Python-list
mailing list