Tom Lane wrote:

> On HPUX 10.20, flock doesn't seem to exist (hasn't got a man page nor
> any mention in /usr/include).

Correct.  Still isn't there in later releases.

>  lockf says
> 
>      All locks for a process are released upon
>      the first close of the file, even if the process still has the file
>      opened, and all locks held by a process are released when the process
>      terminates.
> 
> and
> 
>      When a file descriptor is closed, all locks on the file from the
>      calling process are deleted, even if other file descriptors for that
>      file (obtained through dup() or open(), for example) still exist.
> 
> which seems to imply (but doesn't actually say) that HPUX keeps track of
> exactly which process took out the lock, even if the file is held open
> by multiple processes.

Having done some testing today, I now understand what the standards
are trying to say when they talk about locks being "inherited". Or at
least I think I understand: standards are tricky, locking is subtle,
and I'm prepared to be corrected if I'm wrong!

All of these lock functions succeed when the same process asks for a
lock that it already has.  That is:

     fcntl(fd, ...);
     fcntl(fd, ...);  /* success -- no error returned */

For flock() only, the lock is inherited by a child process along
with the file descriptor so the child can re-issue the flock()
call and that will pass, too:

     flock(fd, ...);
     pid = fork();
     if (pid == 0)
         flock(fd, ...);  /* success -- no error returned */

For fcntl() and lockf() the locks are not inherited, and the
call in a child fails:

     fcntl(fd, ...);
     pid = fork();
     if (pid == 0)
         fcntl(fd, ...);  /* will fail and return -1 */

In no case does just closing the file descriptor in the child lose
the parent's lock.  I rationalise this as follows:

1. flock() is using a "last close" semantic, so closing the file
   descriptor is documented not to lose the lock

2. lockf() and fcntl() use a "first close", but because the locks
   are not inherited by the child process the child can't unlock
   them

> This all doesn't look good for using file locks in the way I had in
> mind :-( ... but considering that all these man pages seem pretty vague,
> maybe some direct experimentation is called for.

I conjecture that Tom was looking for a facility to lock a file and
have it stay locked if the postmaster or any child process was still
running.  flock() fits the bill, but it's not portable everywhere.

One additional warning: this stuff *is* potentially filesystem
dependent, per the source code I looked at, which would call
filesystem specific routines.

I tested with HP-UX 11.00 (VxFS), NetBSD (FFS) and Linux (ext3).  I've
put the rough and ready test code up for FTP, if anyone wants to check
my working:

    ftp://ftp.nemeton.com.au/pub/pgsql/

Limitations in the testing:

I only used whole file locking (no byte ranges) and didn't prove that
a lock taken by flock() is still held after a child calls close() as
it is documented to be.

Regards,

Giles

---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/users-lounge/docs/faq.html

Reply via email to