Re: On file locking

From: Giles Lean <giles(at)nemeton(dot)com(dot)au>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: PostgreSQL Development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: On file locking
Date: 2003-02-03 08:19:39
Message-ID: 1100.1044260379@nemeton.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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'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

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Dave Page 2003-02-03 08:47:14 Re: Interactive Documentation - how do you want it towork?
Previous Message alex avriette 2003-02-03 06:13:05 Re: Irix 6.2, Postgres 7.3.1, some brokenness