Re: On file locking - Mailing list pgsql-hackers

From Giles Lean
Subject Re: On file locking
Date
Msg-id 1100.1044260379@nemeton.com.au
Whole thread Raw
In response to Re: On file locking  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: On file locking  (Antti Haapala <antti.haapala@iki.fi>)
List pgsql-hackers
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'tunlock  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


pgsql-hackers by date:

Previous
From: alex avriette
Date:
Subject: Re: Irix 6.2, Postgres 7.3.1, some brokenness
Next
From: "Dave Page"
Date:
Subject: Re: Interactive Documentation - how do you want it towork?