From 79aab42705a8cb0e16e61c33052fc56fdd4fca76 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 11 Oct 2023 13:38:10 +0300 Subject: [PATCH v3 6/7] Introduce ClientSocket, rename some funcs - Move more of the work on a client socket to the child process. - Reduce the amount of data that needs to be passed from postmaster to child. (Used to pass a full Port struct, although most of the fields were empty. Now we pass the much slimmer ClientSocket.) Reviewed-by: Tristan Partin, Andres Freund Discussion: https://www.postgresql.org/message-id/7a59b073-5b5b-151e-7ed3-8b01ff7ce9ef@iki.fi --- src/backend/libpq/pqcomm.c | 93 +++++++++-------- src/backend/postmaster/postmaster.c | 149 +++++++++++++++------------- src/backend/tcop/postgres.c | 5 +- src/include/libpq/libpq-be.h | 19 ++-- src/include/libpq/libpq.h | 6 +- src/tools/pgindent/typedefs.list | 1 + 6 files changed, 149 insertions(+), 124 deletions(-) diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 2802efc63fc..ccdf1d2140f 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -29,9 +29,9 @@ * INTERFACE ROUTINES * * setup/teardown: - * StreamServerPort - Open postmaster's server port - * StreamConnection - Create new connection with client - * StreamClose - Close a client/backend connection + * ListenServerPort - Open postmaster's server port + * AcceptClientConnection - Create new connection with client + * StreamConnection - Initialize a client connection * TouchSocketFiles - Protect socket files against /tmp cleaners * pq_init - initialize libpq at backend startup * socket_comm_reset - reset libpq during error recovery @@ -304,7 +304,7 @@ socket_close(int code, Datum arg) /* - * StreamServerPort -- open a "listening" port to accept connections. + * ListenServerPort -- open a "listening" port to accept connections. * * family should be AF_UNIX or AF_UNSPEC; portNumber is the port number. * For AF_UNIX ports, hostName should be NULL and unixSocketDir must be @@ -319,7 +319,7 @@ socket_close(int code, Datum arg) * RETURNS: STATUS_OK or STATUS_ERROR */ int -StreamServerPort(int family, const char *hostName, unsigned short portNumber, +ListenServerPort(int family, const char *hostName, unsigned short portNumber, const char *unixSocketDir, pgsocket ListenSockets[], int *NumListenSockets, int MaxListen) { @@ -685,8 +685,9 @@ Setup_AF_UNIX(const char *sock_path) /* - * StreamConnection -- create a new connection with client using - * server port. Set port->sock to the FD of the new connection. + * AcceptClientConnection -- accept a new connection with client using + * server port. Fills *client_sock with the FD and endpoint info + * of the new connection. * * ASSUME: that this doesn't need to be non-blocking because * the Postmaster waits for the socket to be ready to accept(). @@ -694,13 +695,13 @@ Setup_AF_UNIX(const char *sock_path) * RETURNS: STATUS_OK or STATUS_ERROR */ int -StreamConnection(pgsocket server_fd, Port *port) +AcceptClientConnection(pgsocket server_fd, ClientSocket *client_sock) { /* accept connection and fill in the client (remote) address */ - port->raddr.salen = sizeof(port->raddr.addr); - if ((port->sock = accept(server_fd, - (struct sockaddr *) &port->raddr.addr, - &port->raddr.salen)) == PGINVALID_SOCKET) + client_sock->raddr.salen = sizeof(client_sock->raddr.addr); + if ((client_sock->sock = accept(server_fd, + (struct sockaddr *) &client_sock->raddr.addr, + &client_sock->raddr.salen)) == PGINVALID_SOCKET) { ereport(LOG, (errcode_for_socket_access(), @@ -718,10 +719,10 @@ StreamConnection(pgsocket server_fd, Port *port) } /* fill in the server (local) address */ - port->laddr.salen = sizeof(port->laddr.addr); - if (getsockname(port->sock, - (struct sockaddr *) &port->laddr.addr, - &port->laddr.salen) < 0) + client_sock->laddr.salen = sizeof(client_sock->laddr.addr); + if (getsockname(client_sock->sock, + (struct sockaddr *) &client_sock->laddr.addr, + &client_sock->laddr.salen) < 0) { ereport(LOG, (errmsg("%s() failed: %m", "getsockname"))); @@ -729,7 +730,7 @@ StreamConnection(pgsocket server_fd, Port *port) } /* select NODELAY and KEEPALIVE options if it's a TCP connection */ - if (port->laddr.addr.ss_family != AF_UNIX) + if (client_sock->laddr.addr.ss_family != AF_UNIX) { int on; #ifdef WIN32 @@ -740,7 +741,7 @@ StreamConnection(pgsocket server_fd, Port *port) #ifdef TCP_NODELAY on = 1; - if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY, + if (setsockopt(client_sock->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) { ereport(LOG, @@ -749,7 +750,7 @@ StreamConnection(pgsocket server_fd, Port *port) } #endif on = 1; - if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE, + if (setsockopt(client_sock->sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) { ereport(LOG, @@ -781,7 +782,7 @@ StreamConnection(pgsocket server_fd, Port *port) * https://msdn.microsoft.com/en-us/library/bb736549%28v=vs.85%29.aspx */ optlen = sizeof(oldopt); - if (getsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &oldopt, + if (getsockopt(client_sock->sock, SOL_SOCKET, SO_SNDBUF, (char *) &oldopt, &optlen) < 0) { ereport(LOG, @@ -791,7 +792,7 @@ StreamConnection(pgsocket server_fd, Port *port) newopt = PQ_SEND_BUFFER_SIZE * 4; if (oldopt < newopt) { - if (setsockopt(port->sock, SOL_SOCKET, SO_SNDBUF, (char *) &newopt, + if (setsockopt(client_sock->sock, SOL_SOCKET, SO_SNDBUF, (char *) &newopt, sizeof(newopt)) < 0) { ereport(LOG, @@ -800,13 +801,34 @@ StreamConnection(pgsocket server_fd, Port *port) } } #endif + } + return STATUS_OK; +} + +/* + * StreamConnection -- create a new connection from the given socket. + * + * This runs in the backend process. + */ +Port * +StreamConnection(ClientSocket *client_sock) +{ + Port *port; + + port = palloc0(sizeof(Port)); + port->sock = client_sock->sock; + port->laddr = client_sock->laddr; + port->raddr = client_sock->raddr; + /* Apply the current keepalive parameters if it's a TCP connection */ + if (port->laddr.addr.ss_family != AF_UNIX) + { /* - * Also apply the current keepalive parameters. If we fail to set a - * parameter, don't error out, because these aren't universally - * supported. (Note: you might think we need to reset the GUC - * variables to 0 in such a case, but it's not necessary because the - * show hooks for these variables report the truth anyway.) + * If we fail to set a parameter, don't error out, because these + * aren't universally supported. (Note: you might think we need to + * reset the GUC variables to 0 in such a case, but it's not necessary + * because the show hooks for these variables report the truth + * anyway.) */ (void) pq_setkeepalivesidle(tcp_keepalives_idle, port); (void) pq_setkeepalivesinterval(tcp_keepalives_interval, port); @@ -814,24 +836,7 @@ StreamConnection(pgsocket server_fd, Port *port) (void) pq_settcpusertimeout(tcp_user_timeout, port); } - return STATUS_OK; -} - -/* - * StreamClose -- close a client/backend connection - * - * NOTE: this is NOT used to terminate a session; it is just used to release - * the file descriptor in a process that should no longer have the socket - * open. (For example, the postmaster calls this after passing ownership - * of the connection to a child process.) It is expected that someone else - * still has the socket open. So, we only want to close the descriptor, - * we do NOT want to send anything to the far end. - */ -void -StreamClose(pgsocket sock) -{ - if (closesocket(sock) != 0) - elog(LOG, "could not close client or listen socket: %m"); + return port; } /* diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index dcec983e7d9..550136009a8 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -427,15 +427,15 @@ typedef enum CAC_state CAC_TOOMANY, } CAC_state; -static void BackendInitialize(Port *port, CAC_state cac); -static void BackendRun(Port *port) pg_attribute_noreturn(); +static void BackendInitialize(ClientSocket *client_sock, CAC_state cac); +static void BackendRun(void) pg_attribute_noreturn(); static void ExitPostmaster(int status) pg_attribute_noreturn(); static int ServerLoop(void); -static int BackendStartup(Port *port); +static int BackendStartup(ClientSocket *port); static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done); static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options); static void processCancelRequest(Port *port, void *pkt); -static void report_fork_failure_to_client(Port *port, int errnum); +static void report_fork_failure_to_client(ClientSocket *client_sock, int errnum); static CAC_state canAcceptConnections(int backend_type); static bool RandomCancelKey(int32 *cancel_key); static void signal_child(pid_t pid, int signal); @@ -484,8 +484,8 @@ typedef struct } win32_deadchild_waitinfo; #endif /* WIN32 */ -static pid_t backend_forkexec(Port *port, CAC_state cac); -static pid_t internal_forkexec(int argc, char *argv[], Port *port); +static pid_t backend_forkexec(ClientSocket *client_sock, CAC_state cac); +static pid_t internal_forkexec(int argc, char *argv[], ClientSocket *client_sock); /* Type for a socket that can be inherited to a client process */ #ifdef WIN32 @@ -504,8 +504,8 @@ typedef int InheritableSocket; */ typedef struct { - Port port; - InheritableSocket portsocket; + ClientSocket client_sock; + InheritableSocket serialized_sock; char DataDir[MAXPGPATH]; int32 MyCancelKey; int MyPMChildSlot; @@ -553,13 +553,13 @@ typedef struct BackgroundWorker MyBgworkerEntry; } BackendParameters; -static void read_backend_variables(char *id, Port *port); -static void restore_backend_variables(BackendParameters *param, Port *port); +static void read_backend_variables(char *id, ClientSocket *client_sock); +static void restore_backend_variables(BackendParameters *param, ClientSocket *client_sock); #ifndef WIN32 -static bool save_backend_variables(BackendParameters *param, Port *port); +static bool save_backend_variables(BackendParameters *param, ClientSocket *client_sock); #else -static bool save_backend_variables(BackendParameters *param, Port *port, +static bool save_backend_variables(BackendParameters *param, ClientSocket *client_sock, HANDLE childProcess, pid_t childPid); #endif @@ -1219,14 +1219,14 @@ PostmasterMain(int argc, char *argv[]) char *curhost = (char *) lfirst(l); if (strcmp(curhost, "*") == 0) - status = StreamServerPort(AF_UNSPEC, NULL, + status = ListenServerPort(AF_UNSPEC, NULL, (unsigned short) PostPortNumber, NULL, ListenSockets, &NumListenSockets, MAXLISTEN); else - status = StreamServerPort(AF_UNSPEC, curhost, + status = ListenServerPort(AF_UNSPEC, curhost, (unsigned short) PostPortNumber, NULL, ListenSockets, @@ -1320,7 +1320,7 @@ PostmasterMain(int argc, char *argv[]) { char *socketdir = (char *) lfirst(l); - status = StreamServerPort(AF_UNIX, NULL, + status = ListenServerPort(AF_UNIX, NULL, (unsigned short) PostPortNumber, socketdir, ListenSockets, @@ -1500,7 +1500,7 @@ CloseServerPorts(int status, Datum arg) * condition if a new postmaster wants to re-use the TCP port number. */ for (i = 0; i < NumListenSockets; i++) - StreamClose(ListenSockets[i]); + closesocket(ListenSockets[i]); NumListenSockets = 0; /* @@ -1770,18 +1770,20 @@ ServerLoop(void) if (events[i].events & WL_SOCKET_ACCEPT) { - Port port; + ClientSocket s; - memset(&port, 0, sizeof(port)); - if (StreamConnection(events[i].fd, &port) == STATUS_OK) - BackendStartup(&port); + if (AcceptClientConnection(events[i].fd, &s) == STATUS_OK) + BackendStartup(&s); /* * We no longer need the open socket or port structure in this * process */ - if (port.sock != PGINVALID_SOCKET) - StreamClose(port.sock); + if (s.sock != PGINVALID_SOCKET) + { + if (closesocket(s.sock) != 0) + elog(LOG, "could not close client socket: %m"); + } } } @@ -2146,11 +2148,7 @@ retry1: /* * Now fetch parameters out of startup packet and save them into the Port - * structure. All data structures attached to the Port struct must be - * allocated in TopMemoryContext so that they will remain available in a - * running backend (even after PostmasterContext is destroyed). We need - * not worry about leaking this storage on failure, since we aren't in the - * postmaster process anymore. + * structure. */ oldcontext = MemoryContextSwitchTo(TopMemoryContext); @@ -2286,7 +2284,7 @@ retry1: port->database_name[0] = '\0'; /* - * Done putting stuff in TopMemoryContext. + * Done filling the Port structure */ MemoryContextSwitchTo(oldcontext); @@ -2490,7 +2488,10 @@ ClosePostmasterPorts(bool am_syslogger) if (ListenSockets) { for (int i = 0; i < NumListenSockets; i++) - StreamClose(ListenSockets[i]); + { + if (closesocket(ListenSockets[i]) != 0) + elog(LOG, "could not close listen socket: %m"); + } pfree(ListenSockets); } NumListenSockets = 0; @@ -3996,7 +3997,7 @@ TerminateChildren(int signal) * Note: if you change this code, also consider StartAutovacuumWorker. */ static int -BackendStartup(Port *port) +BackendStartup(ClientSocket *client_sock) { Backend *bn; /* for backend cleanup */ pid_t pid; @@ -4047,7 +4048,7 @@ BackendStartup(Port *port) bn->bgworker_notify = false; #ifdef EXEC_BACKEND - pid = backend_forkexec(port, cac); + pid = backend_forkexec(client_sock, cac); #else /* !EXEC_BACKEND */ pid = fork_process(); if (pid == 0) /* child */ @@ -4059,10 +4060,10 @@ BackendStartup(Port *port) ClosePostmasterPorts(false); /* Perform additional initialization and collect startup packet */ - BackendInitialize(port, cac); + BackendInitialize(client_sock, cac); /* And run the backend */ - BackendRun(port); + BackendRun(); } #endif /* EXEC_BACKEND */ @@ -4077,14 +4078,14 @@ BackendStartup(Port *port) errno = save_errno; ereport(LOG, (errmsg("could not fork new process for connection: %m"))); - report_fork_failure_to_client(port, save_errno); + report_fork_failure_to_client(client_sock, save_errno); return STATUS_ERROR; } /* in parent, successful fork */ ereport(DEBUG2, (errmsg_internal("forked new backend, pid=%d socket=%d", - (int) pid, (int) port->sock))); + (int) pid, (int) client_sock->sock))); /* * Everything's been successful, it's safe to add this backend to our list @@ -4111,7 +4112,7 @@ BackendStartup(Port *port) * it's not up and running. */ static void -report_fork_failure_to_client(Port *port, int errnum) +report_fork_failure_to_client(ClientSocket *client_sock, int errnum) { char buffer[1000]; int rc; @@ -4122,13 +4123,13 @@ report_fork_failure_to_client(Port *port, int errnum) strerror(errnum)); /* Set port to non-blocking. Don't do send() if this fails */ - if (!pg_set_noblock(port->sock)) + if (!pg_set_noblock(client_sock->sock)) return; /* We'll retry after EINTR, but ignore all other failures */ do { - rc = send(port->sock, buffer, strlen(buffer) + 1, 0); + rc = send(client_sock->sock, buffer, strlen(buffer) + 1, 0); } while (rc < 0 && errno == EINTR); } @@ -4146,16 +4147,28 @@ report_fork_failure_to_client(Port *port, int errnum) * but have not yet set up most of our local pointers to shmem structures. */ static void -BackendInitialize(Port *port, CAC_state cac) +BackendInitialize(ClientSocket *client_sock, CAC_state cac) { int status; int ret; + Port *port; char remote_host[NI_MAXHOST]; char remote_port[NI_MAXSERV]; StringInfoData ps_data; + MemoryContext oldcontext; - /* Save port etc. for ps status */ + /* + * Create the Port structure. + * + * The Port structure and all data structures attached to it are allocated + * in TopMemoryContext, so that they survive into PostgresMain execution. + * We need not worry about leaking this storage on failure, since we + * aren't in the postmaster process anymore. + */ + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + port = StreamConnection(client_sock); MyProcPort = port; + MemoryContextSwitchTo(oldcontext); /* Tell fd.c about the long-lived FD associated with the port */ ReserveExternalFD(); @@ -4216,8 +4229,9 @@ BackendInitialize(Port *port, CAC_state cac) * Save remote_host and remote_port in port structure (after this, they * will appear in log_line_prefix data for log messages). */ - port->remote_host = strdup(remote_host); - port->remote_port = strdup(remote_port); + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + port->remote_host = pstrdup(remote_host); + port->remote_port = pstrdup(remote_port); /* And now we can issue the Log_connections message, if wanted */ if (Log_connections) @@ -4248,7 +4262,8 @@ BackendInitialize(Port *port, CAC_state cac) ret == 0 && strspn(remote_host, "0123456789.") < strlen(remote_host) && strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host)) - port->remote_hostname = strdup(remote_host); + port->remote_hostname = pstrdup(remote_host); + MemoryContextSwitchTo(oldcontext); /* * Ready to begin client interaction. We will give up and _exit(1) after @@ -4369,7 +4384,7 @@ BackendInitialize(Port *port, CAC_state cac) * Doesn't return at all. */ static void -BackendRun(Port *port) +BackendRun(void) { /* * Create a per-backend PGPROC struct in shared memory. We must do this @@ -4383,7 +4398,7 @@ BackendRun(Port *port) */ MemoryContextSwitchTo(TopMemoryContext); - PostgresMain(port->database_name, port->user_name); + PostgresMain(MyProcPort->database_name, MyProcPort->user_name); } @@ -4404,11 +4419,11 @@ BackendRun(Port *port) pid_t postmaster_forkexec(int argc, char *argv[]) { - Port port; + ClientSocket client_sock; - /* This entry point passes dummy values for the Port variables */ - memset(&port, 0, sizeof(port)); - return internal_forkexec(argc, argv, &port); + /* This entry point doesn't pass a client socket */ + memset(&client_sock, 0, sizeof(ClientSocket)); + return internal_forkexec(argc, argv, &client_sock); } /* @@ -4421,7 +4436,7 @@ postmaster_forkexec(int argc, char *argv[]) * returns the pid of the fork/exec'd process, or -1 on failure */ static pid_t -backend_forkexec(Port *port, CAC_state cac) +backend_forkexec(ClientSocket *client_sock, CAC_state cac) { char *av[5]; int ac = 0; @@ -4437,7 +4452,7 @@ backend_forkexec(Port *port, CAC_state cac) av[ac] = NULL; Assert(ac < lengthof(av)); - return internal_forkexec(ac, av, port); + return internal_forkexec(ac, av, client_sock); } #ifndef WIN32 @@ -4449,7 +4464,7 @@ backend_forkexec(Port *port, CAC_state cac) * - fork():s, and then exec():s the child process */ static pid_t -internal_forkexec(int argc, char *argv[], Port *port) +internal_forkexec(int argc, char *argv[], ClientSocket *client_sock) { static unsigned long tmpBackendFileNum = 0; pid_t pid; @@ -4457,7 +4472,7 @@ internal_forkexec(int argc, char *argv[], Port *port) BackendParameters param; FILE *fp; - if (!save_backend_variables(¶m, port)) + if (!save_backend_variables(¶m, client_sock)) return -1; /* log made by save_backend_variables */ /* Calculate name for temp file */ @@ -4755,7 +4770,7 @@ retry: void SubPostmasterMain(int argc, char *argv[]) { - Port port; + ClientSocket client_sock; /* In EXEC_BACKEND case we will not have inherited these settings */ IsPostmasterEnvironment = true; @@ -4769,8 +4784,8 @@ SubPostmasterMain(int argc, char *argv[]) elog(FATAL, "invalid subpostmaster invocation"); /* Read in the variables file */ - memset(&port, 0, sizeof(Port)); - read_backend_variables(argv[2], &port); + memset(&client_sock, 0, sizeof(ClientSocket)); + read_backend_variables(argv[2], &client_sock); /* Close the postmaster's sockets (as soon as we know them) */ ClosePostmasterPorts(strcmp(argv[1], "--forklog") == 0); @@ -4874,13 +4889,13 @@ SubPostmasterMain(int argc, char *argv[]) * PGPROC slots, we have already initialized libpq and are able to * report the error to the client. */ - BackendInitialize(&port, cac); + BackendInitialize(&client_sock, cac); /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); /* And run the backend */ - BackendRun(&port); /* does not return */ + BackendRun(); /* does not return */ } if (strcmp(argv[1], "--forkaux") == 0) { @@ -5968,15 +5983,15 @@ static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src); /* Save critical backend variables into the BackendParameters struct */ #ifndef WIN32 static bool -save_backend_variables(BackendParameters *param, Port *port) +save_backend_variables(BackendParameters *param, ClientSocket *client_sock) #else static bool -save_backend_variables(BackendParameters *param, Port *port, +save_backend_variables(BackendParameters *param, ClientSocket *client_sock, HANDLE childProcess, pid_t childPid) #endif { - memcpy(¶m->port, port, sizeof(Port)); - if (!write_inheritable_socket(¶m->portsocket, port->sock, childPid)) + memcpy(¶m->client_sock, client_sock, sizeof(ClientSocket)); + if (!write_inheritable_socket(¶m->serialized_sock, client_sock->sock, childPid)) return false; strlcpy(param->DataDir, DataDir, MAXPGPATH); @@ -6138,7 +6153,7 @@ read_inheritable_socket(SOCKET *dest, InheritableSocket *src) #endif static void -read_backend_variables(char *id, Port *port) +read_backend_variables(char *id, ClientSocket *client_sock) { BackendParameters param; @@ -6205,15 +6220,15 @@ read_backend_variables(char *id, Port *port) } #endif - restore_backend_variables(¶m, port); + restore_backend_variables(¶m, client_sock); } /* Restore critical backend variables from the BackendParameters struct */ static void -restore_backend_variables(BackendParameters *param, Port *port) +restore_backend_variables(BackendParameters *param, ClientSocket *client_sock) { - memcpy(port, ¶m->port, sizeof(Port)); - read_inheritable_socket(&port->sock, ¶m->portsocket); + memcpy(client_sock, ¶m->client_sock, sizeof(ClientSocket)); + read_inheritable_socket(&client_sock->sock, ¶m->serialized_sock); SetDataDir(param->DataDir); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index fdf51ce281a..9a9a1e70039 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4213,10 +4213,7 @@ PostgresMain(const char *dbname, const char *username) /* * If the PostmasterContext is still around, recycle the space; we don't - * need it anymore after InitPostgres completes. Note this does not trash - * *MyProcPort, because that space is allocated in stack - * ... else we'd need to copy the Port data first. Also, subsidiary data - * such as the username isn't lost either; see ProcessStartupPacket(). + * need it anymore after InitPostgres completes. */ if (PostmasterContext) { diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index 335cb2de44a..9b6d8fc5571 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -110,12 +110,9 @@ typedef struct ClientConnectionInfo } ClientConnectionInfo; /* - * This is used by the postmaster in its communication with frontends. It - * contains all state information needed during this communication before the - * backend is run. The Port structure is kept in malloc'd memory and is - * still available when a backend is running (see MyProcPort). The data - * it points to must also be malloc'd, or else palloc'd in TopMemoryContext, - * so that it survives into PostgresMain execution! + * The Port structure holds state information about a client connection in a + * backend process. It is available in the global variable MyProcPort. The + * struct and all the data it points are kept in TopMemoryContext. * * remote_hostname is set if we did a successful reverse lookup of the * client's IP address during connection setup. @@ -217,6 +214,16 @@ typedef struct Port #endif } Port; +/* + * ClientSocket holds a socket for an accepted connection, along with the + * information about the endpoints. + */ +typedef struct ClientSocket { + pgsocket sock; /* File descriptor */ + SockAddr laddr; /* local addr (postmaster) */ + SockAddr raddr; /* remote addr (client) */ +} ClientSocket; + #ifdef USE_SSL /* * Hardcoded DH parameters, used in ephemeral DH keying. (See also diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index a6104d8cd02..889e86a7f61 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -64,11 +64,11 @@ extern PGDLLIMPORT WaitEventSet *FeBeWaitSet; #define FeBeWaitSetLatchPos 1 #define FeBeWaitSetNEvents 3 -extern int StreamServerPort(int family, const char *hostName, +extern int ListenServerPort(int family, const char *hostName, unsigned short portNumber, const char *unixSocketDir, pgsocket ListenSocket[], int *NumListenSockets, int MaxListen); -extern int StreamConnection(pgsocket server_fd, Port *port); -extern void StreamClose(pgsocket sock); +extern int AcceptClientConnection(pgsocket server_fd, ClientSocket *client_sock); +extern Port *StreamConnection(ClientSocket *client_sock); extern void TouchSocketFiles(void); extern void RemoveSocketFiles(void); extern void pq_init(void); diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index d659adbfd6c..00649608e46 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -382,6 +382,7 @@ ClientCertMode ClientCertName ClientConnectionInfo ClientData +ClientSocket ClonePtrType ClosePortalStmt ClosePtrType -- 2.39.2