4242 * StreamServerPort - Open postmaster's server port
4343 * StreamConnection - Create new connection with client
4444 * StreamClose - Close a client/backend connection
45- * TouchSocketFile - Protect socket file against /tmp cleaners
45+ * TouchSocketFiles - Protect socket files against /tmp cleaners
4646 * pq_init - initialize libpq at backend startup
4747 * pq_comm_reset - reset libpq during error recovery
4848 * pq_close - shutdown libpq at backend exit
@@ -103,8 +103,8 @@ int Unix_socket_permissions;
103103char * Unix_socket_group ;
104104
105105
106- /* Where the Unix socket file is */
107- static char sock_path [ MAXPGPATH ] ;
106+ /* Where the Unix socket files are (list of palloc'd strings) */
107+ static List * sock_paths = NIL ;
108108
109109
110110/*
@@ -140,8 +140,8 @@ static int internal_flush(void);
140140static void pq_set_nonblocking (bool nonblocking );
141141
142142#ifdef HAVE_UNIX_SOCKETS
143- static int Lock_AF_UNIX (unsigned short portNumber , char * unixSocketName );
144- static int Setup_AF_UNIX (void );
143+ static int Lock_AF_UNIX (char * unixSocketDir , char * unixSocketPath );
144+ static int Setup_AF_UNIX (char * sock_path );
145145#endif /* HAVE_UNIX_SOCKETS */
146146
147147
@@ -234,29 +234,43 @@ pq_close(int code, Datum arg)
234234
235235/* StreamDoUnlink()
236236 * Shutdown routine for backend connection
237- * If a Unix socket is used for communication, explicitly close it .
237+ * If any Unix sockets are used for communication, explicitly close them .
238238 */
239239#ifdef HAVE_UNIX_SOCKETS
240240static void
241241StreamDoUnlink (int code , Datum arg )
242242{
243- Assert (sock_path [0 ]);
244- unlink (sock_path );
243+ ListCell * l ;
244+
245+ /* Loop through all created sockets... */
246+ foreach (l , sock_paths )
247+ {
248+ char * sock_path = (char * ) lfirst (l );
249+
250+ unlink (sock_path );
251+ }
252+ /* Since we're about to exit, no need to reclaim storage */
253+ sock_paths = NIL ;
245254}
246255#endif /* HAVE_UNIX_SOCKETS */
247256
248257/*
249258 * StreamServerPort -- open a "listening" port to accept connections.
250259 *
251- * Successfully opened sockets are added to the ListenSocket[] array,
252- * at the first position that isn't PGINVALID_SOCKET.
260+ * family should be AF_UNIX or AF_UNSPEC; portNumber is the port number.
261+ * For AF_UNIX ports, hostName should be NULL and unixSocketDir must be
262+ * specified. For TCP ports, hostName is either NULL for all interfaces or
263+ * the interface to listen on, and unixSocketDir is ignored (can be NULL).
264+ *
265+ * Successfully opened sockets are added to the ListenSocket[] array (of
266+ * length MaxListen), at the first position that isn't PGINVALID_SOCKET.
253267 *
254268 * RETURNS: STATUS_OK or STATUS_ERROR
255269 */
256270
257271int
258272StreamServerPort (int family , char * hostName , unsigned short portNumber ,
259- char * unixSocketName ,
273+ char * unixSocketDir ,
260274 pgsocket ListenSocket [], int MaxListen )
261275{
262276 pgsocket fd ;
@@ -273,6 +287,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
273287 int listen_index = 0 ;
274288 int added = 0 ;
275289
290+ #ifdef HAVE_UNIX_SOCKETS
291+ char unixSocketPath [MAXPGPATH ];
292+ #endif
276293#if !defined(WIN32 ) || defined(IPV6_V6ONLY )
277294 int one = 1 ;
278295#endif
@@ -286,10 +303,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
286303#ifdef HAVE_UNIX_SOCKETS
287304 if (family == AF_UNIX )
288305 {
289- /* Lock_AF_UNIX will also fill in sock_path. */
290- if (Lock_AF_UNIX (portNumber , unixSocketName ) != STATUS_OK )
306+ /*
307+ * Create unixSocketPath from portNumber and unixSocketDir and lock
308+ * that file path
309+ */
310+ UNIXSOCK_PATH (unixSocketPath , portNumber , unixSocketDir );
311+ if (Lock_AF_UNIX (unixSocketDir , unixSocketPath ) != STATUS_OK )
291312 return STATUS_ERROR ;
292- service = sock_path ;
313+ service = unixSocketPath ;
293314 }
294315 else
295316#endif /* HAVE_UNIX_SOCKETS */
@@ -432,7 +453,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
432453 (IS_AF_UNIX (addr -> ai_family )) ?
433454 errhint ("Is another postmaster already running on port %d?"
434455 " If not, remove socket file \"%s\" and retry." ,
435- (int ) portNumber , sock_path ) :
456+ (int ) portNumber , service ) :
436457 errhint ("Is another postmaster already running on port %d?"
437458 " If not, wait a few seconds and retry." ,
438459 (int ) portNumber )));
@@ -443,7 +464,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
443464#ifdef HAVE_UNIX_SOCKETS
444465 if (addr -> ai_family == AF_UNIX )
445466 {
446- if (Setup_AF_UNIX () != STATUS_OK )
467+ if (Setup_AF_UNIX (service ) != STATUS_OK )
447468 {
448469 closesocket (fd );
449470 break ;
@@ -490,10 +511,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
490511 * Lock_AF_UNIX -- configure unix socket file path
491512 */
492513static int
493- Lock_AF_UNIX (unsigned short portNumber , char * unixSocketName )
514+ Lock_AF_UNIX (char * unixSocketDir , char * unixSocketPath )
494515{
495- UNIXSOCK_PATH (sock_path , portNumber , unixSocketName );
496-
497516 /*
498517 * Grab an interlock file associated with the socket file.
499518 *
@@ -502,13 +521,23 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
502521 * more portable, and second, it lets us remove any pre-existing socket
503522 * file without race conditions.
504523 */
505- CreateSocketLockFile (sock_path , true);
524+ CreateSocketLockFile (unixSocketPath , true, unixSocketDir );
506525
507526 /*
508527 * Once we have the interlock, we can safely delete any pre-existing
509528 * socket file to avoid failure at bind() time.
510529 */
511- unlink (sock_path );
530+ unlink (unixSocketPath );
531+
532+ /*
533+ * Arrange to unlink the socket file(s) at proc_exit. If this is the
534+ * first one, set up the on_proc_exit function to do it; then add this
535+ * socket file to the list of files to unlink.
536+ */
537+ if (sock_paths == NIL )
538+ on_proc_exit (StreamDoUnlink , 0 );
539+
540+ sock_paths = lappend (sock_paths , pstrdup (unixSocketPath ));
512541
513542 return STATUS_OK ;
514543}
@@ -518,11 +547,8 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
518547 * Setup_AF_UNIX -- configure unix socket permissions
519548 */
520549static int
521- Setup_AF_UNIX (void )
550+ Setup_AF_UNIX (char * sock_path )
522551{
523- /* Arrange to unlink the socket file at exit */
524- on_proc_exit (StreamDoUnlink , 0 );
525-
526552 /*
527553 * Fix socket ownership/permission if requested. Note we must do this
528554 * before we listen() to avoid a window where unwanted connections could
@@ -704,20 +730,24 @@ StreamClose(pgsocket sock)
704730}
705731
706732/*
707- * TouchSocketFile -- mark socket file as recently accessed
733+ * TouchSocketFiles -- mark socket files as recently accessed
708734 *
709735 * This routine should be called every so often to ensure that the socket
710- * file has a recent mod date (ordinary operations on sockets usually won't
711- * change the mod date). That saves it from being removed by
736+ * files have a recent mod date (ordinary operations on sockets usually won't
737+ * change the mod date). That saves them from being removed by
712738 * overenthusiastic /tmp-directory-cleaner daemons. (Another reason we should
713739 * never have put the socket file in /tmp...)
714740 */
715741void
716- TouchSocketFile (void )
742+ TouchSocketFiles (void )
717743{
718- /* Do nothing if we did not create a socket... */
719- if (sock_path [0 ] != '\0' )
744+ ListCell * l ;
745+
746+ /* Loop through all created sockets... */
747+ foreach (l , sock_paths )
720748 {
749+ char * sock_path = (char * ) lfirst (l );
750+
721751 /*
722752 * utime() is POSIX standard, utimes() is a common alternative. If we
723753 * have neither, there's no way to affect the mod or access time of
0 commit comments