Robert Haas <robertmhaas@gmail.com> writes:
> How about this locking protocol:
> Postmaster:
> 1. Acquire an exclusive lock on some file in the data directory, maybe
> the control file, using fcntl().
> 2. Open the named pipe for read.
> 3. Open the named pipe for write.
> 4. Close the named pipe for read.
> 5. Install a signal handler for SIGPIPE which sets a global variable.
> 6. Try to write to the pipe.
> 7. Check that the variable is set; if not, FATAL.
> 8. Revert SIGPIPE handler.
> 9. Close the named pipe for write.
> 10. Open the named pipe for read.
> 11. Release the fcntl() lock acquired in step 1.
Hm, this seems like it would work. A couple other thoughts:
* I think 5..8 are overly complex: we can just set SIGPIPE to SIG_IGN
(which is its usual setting in the postmaster already) and check for
EPIPE from the write().
* There might be some benefit to swapping steps 9 and 10; at the
very least, this would eliminate the need to use O_NONBLOCK while
re-opening for read.
* We talked about combining this technique with a plain file lock
so that we would have belt-and-suspenders protection, in particular
something that would have a chance of working across NFS clients.
This would suggest leaving the fcntl lock in place, ie, don't do
step 11, and also that the file-to-be-locked *not* have any other
purpose (which would only increase the risk of losing the lock
through careless open/close).
> Regular backends don't need to do anything special, except that they
> need to make sure that the file descriptor opened in step 8 gets
> inherited by the right set of processes. That means that the
> close-on-exec flag should be turned on in the postmaster; except in
> EXEC_BACKEND builds, where it should be turned off but then turned on
> again by child processes before they do anything that might fork.
Meh. Do we really want to allow a new postmaster to start if there
are any processes remaining that were launched by backends? I'd
be inclined to just suppress close-on-exec, period.
regards, tom lane