Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 792b0f4

Browse files
committed
Get rid of not-very-portable fcntl(F_SETLK) mechanism for locking the Unix
socket file, in favor of having an ordinary lockfile beside the socket file. Clean up a few robustness problems in the lockfile code. If postmaster is going to reject a connection request based on database state, it will now tell you so before authentication exchange not after. (Of course, a failure after is still possible if conditions change meanwhile, but this makes life easier for a yet-to-be-written pg_ping utility.)
1 parent 1efd733 commit 792b0f4

File tree

10 files changed

+497
-565
lines changed

10 files changed

+497
-565
lines changed

configure

Lines changed: 124 additions & 158 deletions
Large diffs are not rendered by default.

configure.in

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -758,23 +758,6 @@ PGAC_VAR_INT_TIMEZONE
758758
AC_FUNC_ACCEPT_ARGTYPES
759759
PGAC_FUNC_GETTIMEOFDAY_1ARG
760760

761-
AC_MSG_CHECKING([for fcntl(F_SETLK)])
762-
case $host_os in
763-
linux*) AC_MSG_RESULT([broken on Linux]) ;;
764-
*)
765-
AC_TRY_LINK(
766-
[#include <stdio.h>
767-
#include <fcntl.h>
768-
],
769-
[struct flock lck;
770-
lck.l_whence = SEEK_SET; lck.l_start = lck.l_len = 0;
771-
lck.l_type = F_WRLCK;
772-
fcntl(0, F_SETLK, &lck);],
773-
[AC_DEFINE(HAVE_FCNTL_SETLK) AC_MSG_RESULT(yes)],
774-
[AC_MSG_RESULT(no)])
775-
;;
776-
esac
777-
778761
AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen])
779762

780763
AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS],

src/backend/libpq/pqcomm.c

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
3030
* Portions Copyright (c) 1994, Regents of the University of California
3131
*
32-
* $Id: pqcomm.c,v 1.113 2000/11/21 23:03:53 petere Exp $
32+
* $Id: pqcomm.c,v 1.114 2000/11/29 20:59:51 tgl Exp $
3333
*
3434
*-------------------------------------------------------------------------
3535
*/
@@ -169,7 +169,7 @@ StreamDoUnlink(void)
169169
/*
170170
* StreamServerPort -- open a sock stream "listening" port.
171171
*
172-
* This initializes the Postmaster's connection-accepting port fdP.
172+
* This initializes the Postmaster's connection-accepting port *fdP.
173173
*
174174
* RETURNS: STATUS_OK or STATUS_ERROR
175175
*/
@@ -183,9 +183,6 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
183183
err;
184184
size_t len = 0;
185185
int one = 1;
186-
#ifdef HAVE_FCNTL_SETLK
187-
int lock_fd;
188-
#endif
189186

190187
Assert(family == AF_INET || family == AF_UNIX);
191188

@@ -223,22 +220,15 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
223220
len = UNIXSOCK_LEN(saddr.un);
224221
strcpy(sock_path, saddr.un.sun_path);
225222
/*
226-
* If the socket exists but nobody has an advisory lock on it we
227-
* can safely delete the file.
223+
* Grab an interlock file associated with the socket file.
228224
*/
229-
#ifdef HAVE_FCNTL_SETLK
230-
if ((lock_fd = open(sock_path, O_WRONLY | O_NONBLOCK | PG_BINARY, 0666)) >= 0)
231-
{
232-
struct flock lck;
233-
234-
lck.l_whence = SEEK_SET;
235-
lck.l_start = lck.l_len = 0;
236-
lck.l_type = F_WRLCK;
237-
if (fcntl(lock_fd, F_SETLK, &lck) != -1)
238-
unlink(sock_path);
239-
close(lock_fd);
240-
}
241-
#endif /* HAVE_FCNTL_SETLK */
225+
if (! CreateSocketLockFile(sock_path, true))
226+
return STATUS_ERROR;
227+
/*
228+
* Once we have the interlock, we can safely delete any pre-existing
229+
* socket file to avoid failure at bind() time.
230+
*/
231+
unlink(sock_path);
242232
}
243233
#endif /* HAVE_UNIX_SOCKETS */
244234

@@ -274,8 +264,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
274264
{
275265
snprintf(PQerrormsg, PQERRORMSG_LENGTH,
276266
"FATAL: StreamServerPort: bind() failed: %s\n"
277-
"\tIs another postmaster already running on that port?\n",
278-
strerror(errno));
267+
"\tIs another postmaster already running on port %d?\n",
268+
strerror(errno), (int) portNumber);
279269
if (family == AF_UNIX)
280270
snprintf(PQerrormsg + strlen(PQerrormsg),
281271
PQERRORMSG_LENGTH - strlen(PQerrormsg),
@@ -293,41 +283,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
293283
#ifdef HAVE_UNIX_SOCKETS
294284
if (family == AF_UNIX)
295285
{
286+
/* Arrange to unlink the socket file at exit */
296287
on_proc_exit(StreamDoUnlink, 0);
297288

298289
/*
299-
* Open the socket file and get an advisory lock on it. The
300-
* lock_fd is left open to keep the lock.
290+
* Fix socket ownership/permission if requested. Note we must
291+
* do this before we listen() to avoid a window where unwanted
292+
* connections could get accepted.
301293
*/
302-
#ifdef HAVE_FCNTL_SETLK
303-
if ((lock_fd = open(sock_path, O_WRONLY | O_NONBLOCK | PG_BINARY, 0666)) >= 0)
304-
{
305-
struct flock lck;
306-
307-
lck.l_whence = SEEK_SET;
308-
lck.l_start = lck.l_len = 0;
309-
lck.l_type = F_WRLCK;
310-
if (fcntl(lock_fd, F_SETLK, &lck) != 0)
311-
elog(DEBUG, "flock error on %s: %s", sock_path, strerror(errno));
312-
}
313-
#endif /* HAVE_FCNTL_SETLK */
314-
}
315-
#endif /* HAVE_UNIX_SOCKETS */
316-
317-
listen(fd, SOMAXCONN);
318-
319-
/*
320-
* MS: I took this code from Dillon's version. It makes the listening
321-
* port non-blocking. That is not necessary (and may tickle kernel
322-
* bugs).
323-
*
324-
* fcntl(fd, F_SETFD, 1); fcntl(fd, F_SETFL, FNDELAY);
325-
*/
326-
327-
*fdP = fd;
328-
329-
if (family == AF_UNIX)
330-
{
331294
Assert(Unix_socket_group);
332295
if (Unix_socket_group[0] != '\0')
333296
{
@@ -379,6 +342,12 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
379342
return STATUS_ERROR;
380343
}
381344
}
345+
#endif /* HAVE_UNIX_SOCKETS */
346+
347+
listen(fd, SOMAXCONN);
348+
349+
*fdP = fd;
350+
382351
return STATUS_OK;
383352
}
384353

0 commit comments

Comments
 (0)