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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy