Question: posix fcntl module

Sheila King sheila at spamcop.net
Tue Aug 28 18:09:09 EDT 2001


On Tue, 28 Aug 2001 21:25:51 GMT, Sheila King <sheila at spamcop.net> wrote in
comp.lang.python in article <bo2ootg61vmposfvsg8gvrks6eqiuss940 at 4ax.com>:

:I have a question about file locking aspect of the fcntl module for Unix
:systems.
...<snipped>...

related to this question, I have something else that is really confusing me.

I've written the following module, to wrap two different 
platform specific modules:

---------------(begin LockFile.py)--------------------------
'''LockFile.py

wraps WinLock.py and posixLock.py to provide
a single interface for working with locked files
across win32 and posix platforms.
Does not support fine-grained locking.
Recommended for getting a lock on a sentinel file
before trying to read/write data to a separate data file.
'''
import os

if os.name == 'nt':
     from WinLock import lockfile
elif os.name == 'posix':
     from posixLock import lockfile
else:
    raise ImportError, "LockFile is not supported on your platform."


class LockFile(lockfile):
    pass
---------------(end LockFile.py)--------------------------



And here is the posixLock.py module, that is imported on posix systems:

------------------(begin posixLock.py)------------------------
''' 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.flock(self.fd, fcntl.LOCK_SH)

    def getWriteLock(self):
        self.f = open(self.filename)
        self.fd = self.f.fileno()
        fcntl.flock(self.fd, fcntl.LOCK_EX)

    def unlock(self):
        fcntl.flock(self.fd, fcntl.LOCK_UN)
        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

-------------------(end posixLock.py)-------------------------


Now, the above seems to run alright on the Linux system that I have access to.
Here is a brief interactive session, which doesn't show much, except 
that at least the calls to the function don't generate error messages:

Python 2.1.1 (#6, Aug 16 2001, 17:02:08)
[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> from LockFile import LockFile
>>> obj = LockFile('lock.txt')
>>> obj.flock('LOCK_SH')
>>> obj.flock('LOCK_UN')
>>> obj.flock('LOCK_EX')
>>> obj.flock('LOCK_UN')
>>>

Now, here's the kicker:
If I change the fcntl.flock calls in the posixLock.py file to fcntl.lockf
class, then I do get errors when I try the same interactive session.
Namely:

[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> from LockFile import LockFile
>>> obj = LockFile('lock.txt')
>>> obj.flock('LOCK_SH')
>>> obj.flock('LOCK_UN')
>>> obj.flock('LOCK_EX')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "posixLock.py", line 44, in flock
    self.getWriteLock()
  File "posixLock.py", line 28, in getWriteLock
    fcntl.lockf(self.fd, fcntl.LOCK_EX)
IOError: [Errno 9] Bad file descriptor
>>> obj2 = LockFile('datafile.txt')
>>> obj2.flock('LOCK_EX')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "posixLock.py", line 44, in flock
    self.getWriteLock()
  File "posixLock.py", line 28, in getWriteLock
    fcntl.lockf(self.fd, fcntl.LOCK_EX)
IOError: [Errno 9] Bad file descriptor
>>>


So, it appears to be the LOCK_EX flag that is precipitating the error
messages. It doesn't matter whether the call to Lock the file is
on a previously instantiated object, or a fresh, brand new on that
has previously not locked on the file, and the file has not been locked by
anyone else.

I'm quite puzzled, especially since the docs say that lockf is just a wrapped,
the function works fine for flock.

I thought it would be good to use lockf instead of flock, since it appears
to handle more cases than flock does. However, if it generates an error message
every time I try to get an exclusive lock it won't do me a whole bunch of good.

Does anyone have any ideas what I might be doing wrong?

--
Sheila King
http://www.thinkspot.net/sheila/
http://www.k12groups.org/




More information about the Python-list mailing list