42
42
*StreamServerPort- Open postmaster's server port
43
43
*StreamConnection- Create new connection with client
44
44
*StreamClose- Close a client/backend connection
45
- *TouchSocketFile - Protect socketfile against /tmp cleaners
45
+ *TouchSocketFiles - Protect socketfiles against /tmp cleaners
46
46
*pq_init- initialize libpq at backend startup
47
47
*pq_comm_reset- reset libpq during error recovery
48
48
*pq_close- shutdown libpq at backend exit
@@ -103,8 +103,8 @@ intUnix_socket_permissions;
103
103
char * Unix_socket_group ;
104
104
105
105
106
- /* Where the Unix socketfile is */
107
- static char sock_path [ MAXPGPATH ] ;
106
+ /* Where the Unix socketfiles are (list of palloc'd strings) */
107
+ static List * sock_paths = NIL ;
108
108
109
109
110
110
/*
@@ -140,8 +140,8 @@ static intinternal_flush(void);
140
140
static void pq_set_nonblocking (bool nonblocking );
141
141
142
142
#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 );
145
145
#endif /* HAVE_UNIX_SOCKETS */
146
146
147
147
@@ -234,29 +234,43 @@ pq_close(int code, Datum arg)
234
234
235
235
/* StreamDoUnlink()
236
236
* Shutdown routine for backend connection
237
- * Ifa Unixsocket is used for communication, explicitly closeit .
237
+ * Ifany Unixsockets are used for communication, explicitly closethem .
238
238
*/
239
239
#ifdef HAVE_UNIX_SOCKETS
240
240
static void
241
241
StreamDoUnlink (int code ,Datum arg )
242
242
{
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 ;
245
254
}
246
255
#endif /* HAVE_UNIX_SOCKETS */
247
256
248
257
/*
249
258
* StreamServerPort -- open a "listening" port to accept connections.
250
259
*
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.
253
267
*
254
268
* RETURNS: STATUS_OK or STATUS_ERROR
255
269
*/
256
270
257
271
int
258
272
StreamServerPort (int family ,char * hostName ,unsigned short portNumber ,
259
- char * unixSocketName ,
273
+ char * unixSocketDir ,
260
274
pgsocket ListenSocket [],int MaxListen )
261
275
{
262
276
pgsocket fd ;
@@ -273,6 +287,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
273
287
int listen_index = 0 ;
274
288
int added = 0 ;
275
289
290
+ #ifdef HAVE_UNIX_SOCKETS
291
+ char unixSocketPath [MAXPGPATH ];
292
+ #endif
276
293
#if !defined(WIN32 )|| defined(IPV6_V6ONLY )
277
294
int one = 1 ;
278
295
#endif
@@ -286,10 +303,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
286
303
#ifdef HAVE_UNIX_SOCKETS
287
304
if (family == AF_UNIX )
288
305
{
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 )
291
312
return STATUS_ERROR ;
292
- service = sock_path ;
313
+ service = unixSocketPath ;
293
314
}
294
315
else
295
316
#endif /* HAVE_UNIX_SOCKETS */
@@ -432,7 +453,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
432
453
(IS_AF_UNIX (addr -> ai_family )) ?
433
454
errhint ("Is another postmaster already running on port %d?"
434
455
" If not, remove socket file \"%s\" and retry." ,
435
- (int )portNumber ,sock_path ) :
456
+ (int )portNumber ,service ) :
436
457
errhint ("Is another postmaster already running on port %d?"
437
458
" If not, wait a few seconds and retry." ,
438
459
(int )portNumber )));
@@ -443,7 +464,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
443
464
#ifdef HAVE_UNIX_SOCKETS
444
465
if (addr -> ai_family == AF_UNIX )
445
466
{
446
- if (Setup_AF_UNIX ()!= STATUS_OK )
467
+ if (Setup_AF_UNIX (service )!= STATUS_OK )
447
468
{
448
469
closesocket (fd );
449
470
break ;
@@ -490,10 +511,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
490
511
* Lock_AF_UNIX -- configure unix socket file path
491
512
*/
492
513
static int
493
- Lock_AF_UNIX (unsigned short portNumber ,char * unixSocketName )
514
+ Lock_AF_UNIX (char * unixSocketDir ,char * unixSocketPath )
494
515
{
495
- UNIXSOCK_PATH (sock_path ,portNumber ,unixSocketName );
496
-
497
516
/*
498
517
* Grab an interlock file associated with the socket file.
499
518
*
@@ -502,13 +521,23 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
502
521
* more portable, and second, it lets us remove any pre-existing socket
503
522
* file without race conditions.
504
523
*/
505
- CreateSocketLockFile (sock_path , true);
524
+ CreateSocketLockFile (unixSocketPath , true, unixSocketDir );
506
525
507
526
/*
508
527
* Once we have the interlock, we can safely delete any pre-existing
509
528
* socket file to avoid failure at bind() time.
510
529
*/
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 ));
512
541
513
542
return STATUS_OK ;
514
543
}
@@ -518,11 +547,8 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
518
547
* Setup_AF_UNIX -- configure unix socket permissions
519
548
*/
520
549
static int
521
- Setup_AF_UNIX (void )
550
+ Setup_AF_UNIX (char * sock_path )
522
551
{
523
- /* Arrange to unlink the socket file at exit */
524
- on_proc_exit (StreamDoUnlink ,0 );
525
-
526
552
/*
527
553
* Fix socket ownership/permission if requested. Note we must do this
528
554
* before we listen() to avoid a window where unwanted connections could
@@ -704,20 +730,24 @@ StreamClose(pgsocket sock)
704
730
}
705
731
706
732
/*
707
- *TouchSocketFile -- mark socketfile as recently accessed
733
+ *TouchSocketFiles -- mark socketfiles as recently accessed
708
734
*
709
735
* 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 savesit from being removed by
736
+ *files have a recent mod date (ordinary operations on sockets usually won't
737
+ * change the mod date). That savesthem from being removed by
712
738
* overenthusiastic /tmp-directory-cleaner daemons. (Another reason we should
713
739
* never have put the socket file in /tmp...)
714
740
*/
715
741
void
716
- TouchSocketFile (void )
742
+ TouchSocketFiles (void )
717
743
{
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 )
720
748
{
749
+ char * sock_path = (char * )lfirst (l );
750
+
721
751
/*
722
752
* utime() is POSIX standard, utimes() is a common alternative. If we
723
753
* have neither, there's no way to affect the mod or access time of