When launching a child backend, take care to close file descriptors for

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 ...
This commit is contained in:
Tom Lane 2001-02-08 00:35:10 +00:00
parent 608ddb7503
commit 897a895d32
1 changed files with 53 additions and 17 deletions

View 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";