new-standalone-mode-2.patch
text/x-patch
Filename: new-standalone-mode-2.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/main/main.c | 0 | 0 |
| src/backend/postmaster/postmaster.c | 0 | 0 |
| src/backend/tcop/postgres.c | 0 | 0 |
| src/include/postmaster/postmaster.h | 0 | 0 |
| src/interfaces/libpq/fe-connect.c | 0 | 0 |
| src/interfaces/libpq/fe-misc.c | 0 | 0 |
| src/interfaces/libpq/fe-protocol3.c | 0 | 0 |
| src/interfaces/libpq/libpq-int.h | 0 | 0 |
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 33c5a0a4e645624515016397da0011423d993c70..968959b85ef53aa2ec0ef8c5c5a9bc544291bfe5 100644
*** a/src/backend/main/main.c
--- b/src/backend/main/main.c
*************** main(int argc, char *argv[])
*** 191,196 ****
--- 191,198 ----
AuxiliaryProcessMain(argc, argv); /* does not return */
else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
GucInfoMain(); /* does not return */
+ else if (argc > 1 && strncmp(argv[1], "--child=", 8) == 0)
+ ChildPostgresMain(argc, argv, get_current_username(progname)); /* does not return */
else if (argc > 1 && strcmp(argv[1], "--single") == 0)
PostgresMain(argc, argv, get_current_username(progname)); /* does not return */
else
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 73520a6ca2f4d3300f3d8939c0e9412064a911c3..5a51fa9cb9abb39b0ac02d21a25e5940159582ea 100644
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
*************** ExitPostmaster(int status)
*** 4268,4273 ****
--- 4268,4350 ----
proc_exit(status);
}
+
+ /*
+ * ChildPostgresMain - start a new-style standalone postgres process
+ *
+ * This may not belong here, but it does share a lot of code with ConnCreate
+ * and BackendInitialize. Basically what it has to do is set up a
+ * MyProcPort structure and then hand off control to PostgresMain.
+ * Beware that not very much stuff is initialized yet.
+ *
+ * In the future it might be interesting to support a "standalone
+ * multiprocess" mode in which we have a postmaster process that doesn't
+ * listen for connections, but does supervise autovacuum, bgwriter, etc
+ * auxiliary processes. So that's another reason why postmaster.c might be
+ * the right place for this.
+ */
+ void
+ ChildPostgresMain(int argc, char *argv[], const char *username)
+ {
+ Port *port;
+
+ /*
+ * Fire up essential subsystems: error and memory management
+ */
+ MemoryContextInit();
+
+ /*
+ * Build a Port structure for the client connection
+ */
+ if (!(port = (Port *) calloc(1, sizeof(Port))))
+ ereport(FATAL,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+
+ /*
+ * GSSAPI specific state struct must exist even though we won't use it
+ */
+ #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
+ port->gss = (pg_gssinfo *) calloc(1, sizeof(pg_gssinfo));
+ if (!port->gss)
+ ereport(FATAL,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+ #endif
+
+ /* The file descriptor of the client socket is the argument of --child */
+ if (sscanf(argv[1], "--child=%d", &port->sock) != 1)
+ ereport(FATAL,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid argument for --child: \"%s\"", argv[1])));
+
+ /* Default assumption about protocol to use */
+ FrontendProtocol = port->proto = PG_PROTOCOL_LATEST;
+
+ /* save process start time */
+ port->SessionStartTime = GetCurrentTimestamp();
+ MyStartTime = timestamptz_to_time_t(port->SessionStartTime);
+
+ /* set these to empty in case they are needed */
+ port->remote_host = "";
+ port->remote_port = "";
+
+ MyProcPort = port;
+
+ /*
+ * We can now initialize libpq and then enable reporting of ereport errors
+ * to the client.
+ */
+ pq_init(); /* initialize libpq to talk to client */
+ whereToSendOutput = DestRemote; /* now safe to ereport to client */
+
+ /* And pass off control to PostgresMain */
+ PostgresMain(argc, argv, username);
+
+ abort(); /* not reached */
+ }
+
+
/*
* sigusr1_handler - handle signal conditions from child processes
*/
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index f1248a851bf90188da8d3a7e8b61ac99bf78ebbd..c6a7de63c77f79c85be2170d4e5254b790f3fd5e 100644
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
*************** process_postgres_switches(int argc, char
*** 3257,3264 ****
{
gucsource = PGC_S_ARGV; /* switches came from command line */
! /* Ignore the initial --single argument, if present */
! if (argc > 1 && strcmp(argv[1], "--single") == 0)
{
argv++;
argc--;
--- 3257,3266 ----
{
gucsource = PGC_S_ARGV; /* switches came from command line */
! /* Ignore the initial --single or --child argument, if present */
! if (argc > 1 &&
! (strcmp(argv[1], "--single") == 0 ||
! strncmp(argv[1], "--child=", 8) == 0))
{
argv++;
argc--;
*************** PostgresMain(int argc, char *argv[], con
*** 3522,3539 ****
* standalone).
*/
if (!IsUnderPostmaster)
- {
MyProcPid = getpid();
MyStartTime = time(NULL);
- }
/*
* Fire up essential subsystems: error and memory management
*
! * If we are running under the postmaster, this is done already.
*/
! if (!IsUnderPostmaster)
MemoryContextInit();
SetProcessingMode(InitProcessing);
--- 3524,3541 ----
* standalone).
*/
if (!IsUnderPostmaster)
MyProcPid = getpid();
+ if (MyProcPort == NULL)
MyStartTime = time(NULL);
/*
* Fire up essential subsystems: error and memory management
*
! * If we are running under the postmaster, this is done already; likewise
! * in child-postgres mode.
*/
! if (MyProcPort == NULL)
MemoryContextInit();
SetProcessingMode(InitProcessing);
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index 0fe7ec26db7646472fca248dee6982dc5c595c6c..6d4245cdc05ea5fea4baccf5dbc52dade7c00ff0 100644
*** a/src/include/postmaster/postmaster.h
--- b/src/include/postmaster/postmaster.h
*************** extern int postmaster_alive_fds[2];
*** 47,52 ****
--- 47,55 ----
extern const char *progname;
extern void PostmasterMain(int argc, char *argv[]) __attribute__((noreturn));
+
+ extern void ChildPostgresMain(int argc, char *argv[], const char *username) __attribute__((noreturn));
+
extern void ClosePostmasterPorts(bool am_syslogger);
extern int MaxLivePostmasterChildren(void);
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 3dcd0c3f9c09ec06144c040cc333e382b9d7f78b..c578a8ebbe6874825afbd0cb27cdfa2a3d01aec7 100644
*** a/src/interfaces/libpq/fe-connect.c
--- b/src/interfaces/libpq/fe-connect.c
***************
*** 17,22 ****
--- 17,23 ----
#include <sys/types.h>
#include <sys/stat.h>
+ #include <sys/wait.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
*************** static const PQconninfoOption PQconninfo
*** 259,264 ****
--- 260,271 ----
{"replication", NULL, NULL, NULL,
"Replication", "D", 5},
+ {"standalone_datadir", NULL, NULL, NULL,
+ "Standalone-Data-Directory", "D", 64},
+
+ {"standalone_backend", NULL, NULL, NULL,
+ "Standalone-Backend", "D", 64},
+
/* Terminating entry --- MUST BE LAST */
{NULL, NULL, NULL, NULL,
NULL, NULL, 0}
*************** pgthreadlock_t pg_g_threadlock = default
*** 345,350 ****
--- 352,390 ----
/*
+ * pqDropConnection
+ *
+ * Close any physical connection to the server, and reset associated
+ * state inside the connection object. We don't release state that
+ * would be needed to reconnect, though.
+ */
+ void
+ pqDropConnection(PGconn *conn)
+ {
+ /* Drop any SSL state */
+ pqsecure_close(conn);
+ /* Close the socket itself */
+ if (conn->sock >= 0)
+ closesocket(conn->sock);
+ conn->sock = -1;
+ /* If we forked a child postgres process, wait for it to exit */
+ if (conn->postgres_pid > 0)
+ {
+ while (waitpid(conn->postgres_pid, NULL, 0) < 0)
+ {
+ /* If interrupted by signal, keep waiting */
+ if (errno != EINTR)
+ break;
+ }
+ }
+ conn->postgres_pid = -1;
+ /* Discard any unread/unsent data */
+ conn->inStart = conn->inCursor = conn->inEnd = 0;
+ conn->outCount = 0;
+ }
+
+
+ /*
* Connecting to a Database
*
* There are now six different ways a user of this API can connect to the
*************** fillPGconn(PGconn *conn, PQconninfoOptio
*** 621,626 ****
--- 661,670 ----
conn->pghost = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "port");
conn->pgport = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "standalone_datadir");
+ conn->standalone_datadir = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "standalone_backend");
+ conn->standalone_backend = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "tty");
conn->pgtty = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "options");
*************** setKeepalivesWin32(PGconn *conn)
*** 1289,1294 ****
--- 1333,1384 ----
#endif /* SIO_KEEPALIVE_VALS */
#endif /* WIN32 */
+ /*
+ * Fork and exec a command, connecting up a pair of anonymous sockets for
+ * communication. argv[fdarg] is modified by appending the child-side
+ * socket's file descriptor number. The parent-side socket's FD is returned
+ * in *psock, and the function result is the child's PID.
+ */
+ static pid_t
+ fork_backend_child(char **argv, int fdarg, int *psock)
+ {
+ pid_t pid;
+ int socks[2];
+ char newfdarg[32];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) < 0)
+ return -1;
+
+ pid = fork();
+
+ if (pid < 0)
+ {
+ /* fork failed */
+ close(socks[0]);
+ close(socks[1]);
+ return pid;
+ }
+ else if (pid == 0)
+ {
+ /* successful, in child process */
+ close(socks[1]);
+ snprintf(newfdarg, sizeof(newfdarg), "%s%d", argv[fdarg], socks[0]);
+ argv[fdarg] = newfdarg;
+ execv(argv[0], argv);
+ perror(argv[0]);
+ exit(1);
+ }
+ else
+ {
+ /* successful, in parent process */
+ close(socks[0]);
+ *psock = socks[1];
+ }
+
+ return pid;
+ }
+
+
/* ----------
* connectDBStart -
* Begin the process of making a connection to the backend.
*************** connectDBStart(PGconn *conn)
*** 1317,1322 ****
--- 1407,1461 ----
conn->outCount = 0;
/*
+ * If the standalone_datadir option was specified, ignore any host or
+ * port specifications and just try to fork a standalone backend.
+ */
+ if (conn->standalone_datadir && conn->standalone_datadir[0])
+ {
+ char *be_argv[10];
+
+ /*
+ * We set up the backend's command line in execv(3) style, so that
+ * we don't need to cope with shell quoting rules.
+ */
+ if (conn->standalone_backend && conn->standalone_backend[0])
+ be_argv[0] = conn->standalone_backend;
+ else /* assume we should use hard-wired path */
+ be_argv[0] = PGBINDIR "/postgres";
+
+ be_argv[1] = "--child=";
+ be_argv[2] = "-D";
+ be_argv[3] = conn->standalone_datadir;
+ be_argv[4] = (conn->dbName && conn->dbName[0]) ? conn->dbName : NULL;
+ be_argv[5] = NULL;
+
+ conn->postgres_pid = fork_backend_child(be_argv, 1, &conn->sock);
+ if (conn->postgres_pid < 0)
+ {
+ char sebuf[256];
+
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("could not fork standalone backend: %s\n"),
+ pqStrerror(errno, sebuf, sizeof(sebuf)));
+ goto connect_errReturn;
+ }
+
+ /*
+ * Go directly to CONNECTION_AUTH_OK state, since the standalone
+ * backend is not going to issue any authentication challenge to us.
+ * We're just waiting for startup to conclude.
+ */
+ #ifdef USE_SSL
+ conn->allow_ssl_try = false;
+ #endif
+ conn->pversion = PG_PROTOCOL(3, 0);
+ conn->status = CONNECTION_AUTH_OK;
+ conn->asyncStatus = PGASYNC_BUSY;
+
+ return 1;
+ }
+
+ /*
* Determine the parameters to pass to pg_getaddrinfo_all.
*/
*************** connectDBStart(PGconn *conn)
*** 1416,1427 ****
return 1;
connect_errReturn:
! if (conn->sock >= 0)
! {
! pqsecure_close(conn);
! closesocket(conn->sock);
! conn->sock = -1;
! }
conn->status = CONNECTION_BAD;
return 0;
}
--- 1555,1561 ----
return 1;
connect_errReturn:
! pqDropConnection(conn);
conn->status = CONNECTION_BAD;
return 0;
}
*************** keep_going: /* We will come back to
*** 1644,1651 ****
{
if (!connectNoDelay(conn))
{
! closesocket(conn->sock);
! conn->sock = -1;
conn->addr_cur = addr_cur->ai_next;
continue;
}
--- 1778,1784 ----
{
if (!connectNoDelay(conn))
{
! pqDropConnection(conn);
conn->addr_cur = addr_cur->ai_next;
continue;
}
*************** keep_going: /* We will come back to
*** 1655,1662 ****
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! closesocket(conn->sock);
! conn->sock = -1;
conn->addr_cur = addr_cur->ai_next;
continue;
}
--- 1788,1794 ----
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! pqDropConnection(conn);
conn->addr_cur = addr_cur->ai_next;
continue;
}
*************** keep_going: /* We will come back to
*** 1667,1674 ****
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! closesocket(conn->sock);
! conn->sock = -1;
conn->addr_cur = addr_cur->ai_next;
continue;
}
--- 1799,1805 ----
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
! pqDropConnection(conn);
conn->addr_cur = addr_cur->ai_next;
continue;
}
*************** keep_going: /* We will come back to
*** 1715,1722 ****
if (err)
{
! closesocket(conn->sock);
! conn->sock = -1;
conn->addr_cur = addr_cur->ai_next;
continue;
}
--- 1846,1852 ----
if (err)
{
! pqDropConnection(conn);
conn->addr_cur = addr_cur->ai_next;
continue;
}
*************** keep_going: /* We will come back to
*** 1802,1812 ****
* failure and keep going if there are more addresses.
*/
connectFailureMessage(conn, SOCK_ERRNO);
! if (conn->sock >= 0)
! {
! closesocket(conn->sock);
! conn->sock = -1;
! }
/*
* Try the next address, if any.
--- 1932,1938 ----
* failure and keep going if there are more addresses.
*/
connectFailureMessage(conn, SOCK_ERRNO);
! pqDropConnection(conn);
/*
* Try the next address, if any.
*************** keep_going: /* We will come back to
*** 1851,1856 ****
--- 1977,1983 ----
* error message.
*/
connectFailureMessage(conn, optval);
+ pqDropConnection(conn);
/*
* If more addresses remain, keep trying, just as in the
*************** keep_going: /* We will come back to
*** 1858,1868 ****
*/
if (conn->addr_cur->ai_next != NULL)
{
- if (conn->sock >= 0)
- {
- closesocket(conn->sock);
- conn->sock = -1;
- }
conn->addr_cur = conn->addr_cur->ai_next;
conn->status = CONNECTION_NEEDED;
goto keep_going;
--- 1985,1990 ----
*************** keep_going: /* We will come back to
*** 2137,2148 ****
/* only retry once */
conn->allow_ssl_try = false;
/* Must drop the old connection */
! closesocket(conn->sock);
! conn->sock = -1;
conn->status = CONNECTION_NEEDED;
- /* Discard any unread/unsent data */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
goto keep_going;
}
}
--- 2259,2266 ----
/* only retry once */
conn->allow_ssl_try = false;
/* Must drop the old connection */
! pqDropConnection(conn);
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
}
*************** keep_going: /* We will come back to
*** 2252,2264 ****
{
conn->pversion = PG_PROTOCOL(2, 0);
/* Must drop the old connection */
! pqsecure_close(conn);
! closesocket(conn->sock);
! conn->sock = -1;
conn->status = CONNECTION_NEEDED;
- /* Discard any unread/unsent data */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
goto keep_going;
}
--- 2370,2377 ----
{
conn->pversion = PG_PROTOCOL(2, 0);
/* Must drop the old connection */
! pqDropConnection(conn);
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
*************** keep_going: /* We will come back to
*** 2323,2334 ****
/* only retry once */
conn->wait_ssl_try = false;
/* Must drop the old connection */
! closesocket(conn->sock);
! conn->sock = -1;
conn->status = CONNECTION_NEEDED;
- /* Discard any unread/unsent data */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
goto keep_going;
}
--- 2436,2443 ----
/* only retry once */
conn->wait_ssl_try = false;
/* Must drop the old connection */
! pqDropConnection(conn);
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
*************** keep_going: /* We will come back to
*** 2343,2355 ****
/* only retry once */
conn->allow_ssl_try = false;
/* Must drop the old connection */
! pqsecure_close(conn);
! closesocket(conn->sock);
! conn->sock = -1;
conn->status = CONNECTION_NEEDED;
- /* Discard any unread/unsent data */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
goto keep_going;
}
#endif
--- 2452,2459 ----
/* only retry once */
conn->allow_ssl_try = false;
/* Must drop the old connection */
! pqDropConnection(conn);
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
#endif
*************** keep_going: /* We will come back to
*** 2509,2521 ****
PQclear(res);
conn->send_appname = false;
/* Must drop the old connection */
! pqsecure_close(conn);
! closesocket(conn->sock);
! conn->sock = -1;
conn->status = CONNECTION_NEEDED;
- /* Discard any unread/unsent data */
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
goto keep_going;
}
}
--- 2613,2620 ----
PQclear(res);
conn->send_appname = false;
/* Must drop the old connection */
! pqDropConnection(conn);
conn->status = CONNECTION_NEEDED;
goto keep_going;
}
}
*************** makeEmptyPGconn(void)
*** 2726,2731 ****
--- 2825,2831 ----
conn->auth_req_received = false;
conn->password_needed = false;
conn->dot_pgpass_used = false;
+ conn->postgres_pid = -1;
#ifdef USE_SSL
conn->allow_ssl_try = true;
conn->wait_ssl_try = false;
*************** freePGconn(PGconn *conn)
*** 2802,2807 ****
--- 2902,2911 ----
free(conn->pgport);
if (conn->pgunixsocket)
free(conn->pgunixsocket);
+ if (conn->standalone_datadir)
+ free(conn->standalone_datadir);
+ if (conn->standalone_backend)
+ free(conn->standalone_backend);
if (conn->pgtty)
free(conn->pgtty);
if (conn->connect_timeout)
*************** closePGconn(PGconn *conn)
*** 2909,2920 ****
/*
* Close the connection, reset all transient state, flush I/O buffers.
*/
! if (conn->sock >= 0)
! {
! pqsecure_close(conn);
! closesocket(conn->sock);
! }
! conn->sock = -1;
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
* absent */
conn->asyncStatus = PGASYNC_IDLE;
--- 3013,3019 ----
/*
* Close the connection, reset all transient state, flush I/O buffers.
*/
! pqDropConnection(conn);
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
* absent */
conn->asyncStatus = PGASYNC_IDLE;
*************** closePGconn(PGconn *conn)
*** 2943,2950 ****
if (conn->lobjfuncs)
free(conn->lobjfuncs);
conn->lobjfuncs = NULL;
- conn->inStart = conn->inCursor = conn->inEnd = 0;
- conn->outCount = 0;
#ifdef ENABLE_GSS
{
OM_uint32 min_s;
--- 3042,3047 ----
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index b5e5519c416aa767921a5549f7947f80e4cf8250..0cd0d4288f1c3a859eebc5708b6a44d7e1c3da52 100644
*** a/src/interfaces/libpq/fe-misc.c
--- b/src/interfaces/libpq/fe-misc.c
*************** retry4:
*** 780,790 ****
* has been set already.
*/
definitelyFailed:
conn->status = CONNECTION_BAD; /* No more connection to backend */
- pqsecure_close(conn);
- closesocket(conn->sock);
- conn->sock = -1;
-
return -1;
}
--- 780,787 ----
* has been set already.
*/
definitelyFailed:
+ pqDropConnection(conn);
conn->status = CONNECTION_BAD; /* No more connection to backend */
return -1;
}
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index d289f82285fea00d5de20542e43ea103493f9e58..c605bcd734c9fd76d15c893db6d66f727bb6d876 100644
*** a/src/interfaces/libpq/fe-protocol3.c
--- b/src/interfaces/libpq/fe-protocol3.c
*************** handleSyncLoss(PGconn *conn, char id, in
*** 430,438 ****
pqSaveErrorResult(conn);
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
! pqsecure_close(conn);
! closesocket(conn->sock);
! conn->sock = -1;
conn->status = CONNECTION_BAD; /* No more connection to backend */
}
--- 430,436 ----
pqSaveErrorResult(conn);
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
! pqDropConnection(conn);
conn->status = CONNECTION_BAD; /* No more connection to backend */
}
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 2bac59c3d879ecabce42ceab3b5133df03a0886a..a9070ace73cead020b8b42f2720eebc771f39e6e 100644
*** a/src/interfaces/libpq/libpq-int.h
--- b/src/interfaces/libpq/libpq-int.h
*************** struct pg_conn
*** 303,308 ****
--- 303,310 ----
char *pgunixsocket; /* the Unix-domain socket that the server is
* listening on; if NULL, uses a default
* constructed from pgport */
+ char *standalone_datadir; /* data directory for standalone backend */
+ char *standalone_backend; /* executable for standalone backend */
char *pgtty; /* tty on which the backend messages is
* displayed (OBSOLETE, NOT USED) */
char *connect_timeout; /* connection timeout (numeric string) */
*************** struct pg_conn
*** 373,378 ****
--- 375,383 ----
bool sigpipe_so; /* have we masked SIGPIPE via SO_NOSIGPIPE? */
bool sigpipe_flag; /* can we mask SIGPIPE via MSG_NOSIGNAL? */
+ /* If we forked a child postgres process, its PID is kept here */
+ pid_t postgres_pid; /* PID, or -1 if none */
+
/* Transient state needed while establishing connection */
struct addrinfo *addrlist; /* list of possible backend addresses */
struct addrinfo *addr_cur; /* the one currently being tried */
*************** extern char *const pgresStatus[];
*** 488,493 ****
--- 493,499 ----
/* === in fe-connect.c === */
+ extern void pqDropConnection(PGconn *conn);
extern int pqPacketSend(PGconn *conn, char pack_type,
const void *buf, size_t buf_len);
extern bool pqGetHomeDirectory(char *buf, int bufsize);