]> granicus.if.org Git - postgresql/commitdiff
When launching a child backend, take care to close file descriptors for
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 8 Feb 2001 00:35:10 +0000 (00:35 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 8 Feb 2001 00:35:10 +0000 (00:35 +0000)
any other client connections that may exist (which would only happen if
another client is currently in the authentication cycle).  This avoids
wastage of open descriptors in a child.  It might also explain peculiar
behaviors like not closing connections when expected, since the kernel
will probably not signal EOF as long as some other backend is randomly
holding open a reference to the connection, even if the client went away
long since ...

src/backend/postmaster/postmaster.c

index 98fff8b6af0ba614751a1c99a7ccfef2bb8cdb2e..763f482608e6abc23135e2b8691a9598a080b368 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.204 2001/01/27 00:05:31 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.205 2001/02/08 00:35:10 tgl Exp $
  *
  * NOTES
  *
@@ -202,6 +202,7 @@ extern void GetRedoRecPtr(void);
 static void pmdaemonize(int argc, char *argv[]);
 static Port *ConnCreate(int serverFd);
 static void ConnFree(Port *port);
+static void ClosePostmasterPorts(Port *myConn);
 static void reset_shared(unsigned short port);
 static void SIGHUP_handler(SIGNAL_ARGS);
 static void pmdie(SIGNAL_ARGS);
@@ -1285,6 +1286,51 @@ ConnFree(Port *conn)
        free(conn);
 }
 
+/*
+ * ClosePostmasterPorts -- close all the postmaster's open sockets
+ *
+ * This is called during child process startup to release file descriptors
+ * that are not needed by that child process.  All descriptors other than
+ * the one for myConn (if it's not null) are closed.
+ *
+ * Note that closing the child's descriptor does not destroy the client
+ * connection prematurely, since the parent (postmaster) process still
+ * has the socket open.
+ */
+static void
+ClosePostmasterPorts(Port *myConn)
+{
+       Dlelem     *curr;
+
+       /* Close the listen sockets */
+       if (NetServer)
+               StreamClose(ServerSock_INET);
+       ServerSock_INET = INVALID_SOCK;
+#ifdef HAVE_UNIX_SOCKETS
+       StreamClose(ServerSock_UNIX);
+       ServerSock_UNIX = INVALID_SOCK;
+#endif
+
+       /* Close any sockets for other clients, and release memory too */
+       curr = DLGetHead(PortList);
+
+       while (curr)
+       {
+               Port       *port = (Port *) DLE_VAL(curr);
+               Dlelem     *next = DLGetSucc(curr);
+
+               if (port != myConn)
+               {
+                       StreamClose(port->sock);
+                       DLRemove(curr);
+                       ConnFree(port);
+                       DLFreeElem(curr);
+               }
+
+               curr = next;
+       }
+}
+
 
 /*
  * reset_shared -- reset shared memory and semaphores
@@ -1918,21 +1964,15 @@ DoBackend(Port *port)
         * Signal handlers setting is moved to tcop/postgres...
         */
 
-       /* Close the postmaster sockets */
-       if (NetServer)
-               StreamClose(ServerSock_INET);
-       ServerSock_INET = INVALID_SOCK;
-#ifdef HAVE_UNIX_SOCKETS
-       StreamClose(ServerSock_UNIX);
-       ServerSock_UNIX = INVALID_SOCK;
-#endif
-
        /* Save port etc. for ps status */
        MyProcPort = port;
 
        /* Reset MyProcPid to new backend's pid */
        MyProcPid = getpid();
 
+       /* Close the postmaster's other sockets */
+       ClosePostmasterPorts(port);
+
        /*
         * Don't want backend to be able to see the postmaster random number
         * generator state.  We have to clobber the static random_seed *and*
@@ -2225,13 +2265,9 @@ SSDataBase(int xlop)
                /* Lose the postmaster's on-exit routines and port connections */
                on_exit_reset();
 
-               if (NetServer)
-                       StreamClose(ServerSock_INET);
-               ServerSock_INET = INVALID_SOCK;
-#ifdef HAVE_UNIX_SOCKETS
-               StreamClose(ServerSock_UNIX);
-               ServerSock_UNIX = INVALID_SOCK;
-#endif
+               /* Close the postmaster's sockets */
+               ClosePostmasterPorts(NULL);
+
 
                av[ac++] = "postgres";