On Mon, May 14, 2007 at 09:34:05AM -0400, Andrew Dunstan wrote:
>
>
> Magnus Hagander wrote:
> >On Mon, May 14, 2007 at 09:02:10AM -0400, Tom Lane wrote:
> >
> >>Magnus Hagander <[EMAIL PROTECTED]> writes:
> >>
> >>>If all we want to do is add a check that prevents two servers to start on
> >>>the same port, we could do that trivially in a win32 specific way (since
> >>>we'll never have unix sockets there). Just create an object in the global
> >>>namespace named postgresql.interlock.<portnumber> or such a thing.
> >>>
> >>Does it go away automatically on postmaster crash?
> >>
> >
> >Yes.
> >
> >
> >
>
> Then I think it's worth adding, and I'd argue that as a low risk safety
> measure we should allow it to sneak into 8.3. I'm assuming the code
> involved will be quite small.
Yes, see attached.
BTW, did you mean 8.2? One typical case where this could happen is in an
upgrade scenario, I think...
//Magnus
Index: src/backend/libpq/pqcomm.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/libpq/pqcomm.c,v
retrieving revision 1.191
diff -c -r1.191 pqcomm.c
*** src/backend/libpq/pqcomm.c 3 Mar 2007 19:32:54 -0000 1.191
--- src/backend/libpq/pqcomm.c 14 May 2007 13:52:05 -0000
***************
*** 261,266 ****
--- 261,291 ----
snprintf(portNumberStr, sizeof(portNumberStr), "%d",
portNumber);
service = portNumberStr;
}
+ #ifdef WIN32
+ /* Win32 doesn't have Unix sockets, but will allow multiple processes
+ * to listen on the same port. This interlock is to prevent that.
+ */
+ {
+ char mutexName[64];
+ HANDLE mutex;
+
+ sprintf(mutexName,"postgresql.interlock.%i", portNumber);
+ mutex = CreateMutex(NULL, FALSE, mutexName);
+ if (mutex == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create
interlocking mutex: %li",
+ GetLastError())));
+
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ ereport(FATAL,
+ (errcode(ERRCODE_LOCK_FILE_EXISTS),
+ errmsg("interlock mutex \"%s\" already
exists", mutexName),
+ errhint("Is another postgres listening
on port %i", portNumber)));
+
+ /* Intentionally leak the handle until process exit, so the
mutex
+ * isn't freed. It will be automatically freed when the process
exits. */
+ }
+ #endif
ret = pg_getaddrinfo_all(hostName, service, &hint, &addrs);
if (ret || !addrs)
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend