fcntl.flock() not working when called from a function

T

thakadu

The following code works as expected when run in the main body of a
python script (ver 2.3.5) on OpenBSD v3.8. but when it is in the body
of a function definition it does not work. It does not raise any errors
but it simply does not block as expected. I have repeated this in both
a cgi envirnoment and a non-cgi environment. I also have repeated it
under OpenBSD 3.6 Python Version 2.3.4. To test this you need to run
the code from two shells or if testing the cgi version from two
browsers.
The first call to flock() should pass without blocking while the second
call should block.
I have tried varying the file open mode by using 'r', 'r+', 'w', 'rw',
'w+', and always I get the same results.
Does anyone have an idea why this would work in the main body of the
script but not in a function?

This code works if in the main body of a script:

import fcntl
f=open('/tmp/lockfile')
fcntl.flock(f,fcntl.LOCK_EX)

but this does not work:

import fcntl

def lock():
f=open('/tmp/lockfile')
fcntl.flock(f,fcntl.LOCK_EX)

lock()
 
J

jepler

The file you open() may be closed as soon as it is no longer possible to refer to it.

So in the first case, because the top-level variable 'f' continues to refer to the opened
file, the file may not be closed.

In the second case, no variable refers to the opened file after lock() returns, so Python is
free to close the file at any time. In fact, Python happens to close the function exactly
when lock() returs.

If you want an open file descriptor that is not automatically closed, use os.open(). Or,
store the file descriptor somewhere so you can later close() or unlock it at an
appropriate time.

Jeff

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

iD8DBQFDa7mIJd01MZaTXX0RAqZAAJ4tMGFkwBW7UqxzEFsDAx4UATWMrACfQ/Kt
6l+08cC3mkR+afgNY0QbI/c=
=NRVX
-----END PGP SIGNATURE-----
 
J

Jim Segrave

The following code works as expected when run in the main body of a
python script (ver 2.3.5) on OpenBSD v3.8. but when it is in the body
of a function definition it does not work. It does not raise any errors
but it simply does not block as expected. I have repeated this in both
a cgi envirnoment and a non-cgi environment. I also have repeated it
under OpenBSD 3.6 Python Version 2.3.4. To test this you need to run
the code from two shells or if testing the cgi version from two
browsers.
The first call to flock() should pass without blocking while the second
call should block.
I have tried varying the file open mode by using 'r', 'r+', 'w', 'rw',
'w+', and always I get the same results.
Does anyone have an idea why this would work in the main body of the
script but not in a function?

This code works if in the main body of a script:

import fcntl
f=open('/tmp/lockfile')
fcntl.flock(f,fcntl.LOCK_EX)

but this does not work:

import fcntl

def lock():
f=open('/tmp/lockfile')
fcntl.flock(f,fcntl.LOCK_EX)

lock()

Doesn't f go out of scope when you exit lock()? Python closes the
file, as it's no longer referenced and Unix removes locks on calls to
close().
To make this work, you'd have to keep a reference to f:

import fcntl

def lock():
f=open('/tmp/lockfile')
fcntl.flock(f,fcntl.LOCK_EX)
return f
saveme = lock()

print "OK"
while True:
pass

Under FreeBSD, the first copy prints OK and waits for a SIGINT, the
second copy prints nothing. Killing the first copy prints OK on the
second one
 
T

thakadu

Thank you both for your replies. You are both quite correct and upon
testing I get the desired results. I was mistakenly expecting the
execution of the function to block at the fcntl.flock(f,fcntl.LOCK_EX)
line.
But I am slowly getting my head around it.

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top