diff options
author | Pavan Deolasee | 2015-06-04 08:02:02 +0000 |
---|---|---|
committer | Pavan Deolasee | 2015-06-04 08:02:02 +0000 |
commit | 1e86f652fa5e214a284f9862c67bb976317ac730 (patch) | |
tree | 2478baa40ebd47196528ee0a5aa6f6921d8e5bd9 /src/backend/tcop/postgres.c | |
parent | 3165b5fde927ff766921270bd56d3236b6c09c21 (diff) | |
parent | 4cb7d671fddc8855c8def2de51fb23df1c8ac0af (diff) |
Merge remote-tracking branch 'remotes/PGSQL/master' into XL_NEW_MASTER
Conflicts:
COPYRIGHT
configure
configure.in
contrib/Makefile
doc/bug.template
src/backend/access/common/heaptuple.c
src/backend/access/common/printtup.c
src/backend/access/transam/Makefile
src/backend/access/transam/clog.c
src/backend/access/transam/twophase.c
src/backend/access/transam/varsup.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/Makefile
src/backend/catalog/catalog.c
src/backend/catalog/dependency.c
src/backend/catalog/genbki.pl
src/backend/catalog/namespace.c
src/backend/catalog/pg_aggregate.c
src/backend/catalog/pg_proc.c
src/backend/catalog/storage.c
src/backend/commands/aggregatecmds.c
src/backend/commands/analyze.c
src/backend/commands/comment.c
src/backend/commands/copy.c
src/backend/commands/dbcommands.c
src/backend/commands/event_trigger.c
src/backend/commands/explain.c
src/backend/commands/indexcmds.c
src/backend/commands/portalcmds.c
src/backend/commands/schemacmds.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/trigger.c
src/backend/commands/vacuum.c
src/backend/commands/variable.c
src/backend/commands/view.c
src/backend/executor/execAmi.c
src/backend/executor/execCurrent.c
src/backend/executor/execMain.c
src/backend/executor/execProcnode.c
src/backend/executor/execTuples.c
src/backend/executor/execUtils.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeModifyTable.c
src/backend/executor/nodeSubplan.c
src/backend/executor/nodeWindowAgg.c
src/backend/libpq/hba.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/planagg.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/plancat.c
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/parser/parse_agg.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_utilcmd.c
src/backend/postmaster/autovacuum.c
src/backend/postmaster/pgstat.c
src/backend/postmaster/postmaster.c
src/backend/replication/logical/decode.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/ipc/ipci.c
src/backend/storage/ipc/procarray.c
src/backend/storage/ipc/procsignal.c
src/backend/storage/lmgr/lock.c
src/backend/storage/lmgr/lwlock.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/dest.c
src/backend/tcop/postgres.c
src/backend/tcop/pquery.c
src/backend/tcop/utility.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/date.c
src/backend/utils/adt/dbsize.c
src/backend/utils/adt/pseudotypes.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/version.c
src/backend/utils/cache/inval.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/plancache.c
src/backend/utils/cache/relcache.c
src/backend/utils/init/globals.c
src/backend/utils/init/miscinit.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/backend/utils/mmgr/portalmem.c
src/backend/utils/sort/tuplesort.c
src/backend/utils/sort/tuplestore.c
src/backend/utils/time/combocid.c
src/backend/utils/time/snapmgr.c
src/bin/Makefile
src/bin/initdb/initdb.c
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_dump/pg_dump.c
src/bin/pgbench/pgbench.c
src/bin/psql/tab-complete.c
src/include/access/htup.h
src/include/access/rmgrlist.h
src/include/access/transam.h
src/include/access/xact.h
src/include/catalog/catalog.h
src/include/catalog/namespace.h
src/include/catalog/pg_aggregate.h
src/include/catalog/pg_namespace.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/commands/explain.h
src/include/commands/sequence.h
src/include/commands/vacuum.h
src/include/commands/variable.h
src/include/executor/execdesc.h
src/include/executor/executor.h
src/include/executor/tuptable.h
src/include/miscadmin.h
src/include/nodes/execnodes.h
src/include/nodes/nodes.h
src/include/nodes/params.h
src/include/nodes/parsenodes.h
src/include/nodes/plannodes.h
src/include/nodes/primnodes.h
src/include/nodes/relation.h
src/include/optimizer/cost.h
src/include/optimizer/pathnode.h
src/include/optimizer/planmain.h
src/include/parser/analyze.h
src/include/parser/parse_agg.h
src/include/parser/parse_utilcmd.h
src/include/pg_config.h.win32
src/include/pgstat.h
src/include/storage/backendid.h
src/include/storage/barrier.h
src/include/storage/lwlock.h
src/include/storage/proc.h
src/include/storage/procarray.h
src/include/storage/procsignal.h
src/include/storage/smgr.h
src/include/tcop/dest.h
src/include/tcop/pquery.h
src/include/utils/builtins.h
src/include/utils/guc.h
src/include/utils/lsyscache.h
src/include/utils/plancache.h
src/include/utils/portal.h
src/include/utils/rel.h
src/include/utils/tuplesort.h
src/include/utils/tuplestore.h
src/test/regress/expected/aggregates.out
src/test/regress/expected/create_index.out
src/test/regress/expected/foreign_data.out
src/test/regress/expected/join.out
src/test/regress/expected/macaddr.out
src/test/regress/expected/polygon.out
src/test/regress/expected/rangetypes.out
src/test/regress/expected/update.out
src/test/regress/input/constraints.source
src/test/regress/pg_regress.c
src/test/regress/serial_schedule
src/test/regress/sql/rangetypes.sql
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 377 |
1 files changed, 193 insertions, 184 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 1173032d81..0f44702dcd 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Portions Copyright (c) 2012-2014, TransLattice, Inc. - * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2010-2012 Postgres-XC Development Group * @@ -28,7 +28,6 @@ #include <fcntl.h> #include <limits.h> #include <signal.h> -#include <time.h> #include <unistd.h> #include <sys/socket.h> #ifdef HAVE_SYS_SELECT_H @@ -349,17 +348,25 @@ InteractiveBackend(StringInfo inBuf) * interactive_getc -- collect one character from stdin * * Even though we are not reading from a "client" process, we still want to - * respond to signals, particularly SIGTERM/SIGQUIT. Hence we must use - * prepare_for_client_read and client_read_ended. + * respond to signals, particularly SIGTERM/SIGQUIT. */ static int interactive_getc(void) { int c; - prepare_for_client_read(); + /* + * This will not process catchup interrupts or notifications while + * reading. But those can't really be relevant for a standalone backend + * anyway. To properly handle SIGTERM there's a hack in die() that + * directly processes interrupts at this stage... + */ + CHECK_FOR_INTERRUPTS(); + c = getc(stdin); - client_read_ended(); + + ProcessClientReadInterrupt(true); + return c; } @@ -473,6 +480,8 @@ SocketBackend(StringInfo inBuf) /* * Get message type code from the frontend. */ + HOLD_CANCEL_INTERRUPTS(); + pq_startmsgread(); qtype = pq_getbyte(); #endif @@ -522,7 +531,7 @@ SocketBackend(StringInfo inBuf) { /* * Can't send DEBUG log messages to client at this - * point.Since we're disconnecting right away, we + * point. Since we're disconnecting right away, we * don't need to restore whereToSendOutput. */ whereToSendOutput = DestNone; @@ -536,8 +545,30 @@ SocketBackend(StringInfo inBuf) break; case 'F': /* fastpath function call */ - /* we let fastpath.c cope with old-style input of this */ doing_extended_query_message = false; + if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) + { + if (GetOldFunctionMessage(inBuf)) + { + if (IsTransactionState()) + ereport(COMMERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("unexpected EOF on client connection with an open transaction"))); + else + { + /* + * Can't send DEBUG log messages to client at this + * point. Since we're disconnecting right away, we + * don't need to restore whereToSendOutput. + */ + whereToSendOutput = DestNone; + ereport(DEBUG1, + (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST), + errmsg("unexpected EOF on client connection"))); + } + return EOF; + } + } break; case 'X': /* terminate */ @@ -616,6 +647,9 @@ SocketBackend(StringInfo inBuf) if (pq_getmessage(inBuf, 0)) return EOF; /* suitable message already logged */ } + else + pq_endmsgread(); + RESUME_CANCEL_INTERRUPTS(); return qtype; } @@ -641,55 +675,79 @@ ReadCommand(StringInfo inBuf) } /* - * prepare_for_client_read -- set up to possibly block on client input + * ProcessClientReadInterrupt() - Process interrupts specific to client reads + * + * This is called just after low-level reads. That might be after the read + * finished successfully, or it was interrupted via interrupt. * - * This must be called immediately before any low-level read from the - * client connection. It is necessary to do it at a sufficiently low level - * that there won't be any other operations except the read kernel call - * itself between this call and the subsequent client_read_ended() call. - * In particular there mustn't be use of malloc() or other potentially - * non-reentrant libc functions. This restriction makes it safe for us - * to allow interrupt service routines to execute nontrivial code while - * we are waiting for input. + * Must preserve errno! */ void -prepare_for_client_read(void) +ProcessClientReadInterrupt(bool blocked) { + int save_errno = errno; + if (DoingCommandRead) { - /* Enable immediate processing of asynchronous signals */ - EnableNotifyInterrupt(); - EnableCatchupInterrupt(); + /* Check for general interrupts that arrived while reading */ + CHECK_FOR_INTERRUPTS(); - /* Allow cancel/die interrupts to be processed while waiting */ - ImmediateInterruptOK = true; + /* Process sinval catchup interrupts that happened while reading */ + if (catchupInterruptPending) + ProcessCatchupInterrupt(); - /* And don't forget to detect one that already arrived */ + /* Process sinval catchup interrupts that happened while reading */ + if (notifyInterruptPending) + ProcessNotifyInterrupt(); + } + else if (ProcDiePending && blocked) + { + /* + * We're dying. It's safe (and sane) to handle that now. + */ CHECK_FOR_INTERRUPTS(); } + + errno = save_errno; } /* - * client_read_ended -- get out of the client-input state + * ProcessClientWriteInterrupt() - Process interrupts specific to client writes + * + * This is called just after low-level writes. That might be after the read + * finished successfully, or it was interrupted via interrupt. 'blocked' tells + * us whether the * - * This is called just after low-level reads. It must preserve errno! + * Must preserve errno! */ void -client_read_ended(void) +ProcessClientWriteInterrupt(bool blocked) { - if (DoingCommandRead) - { - int save_errno = errno; - - ImmediateInterruptOK = false; + int save_errno = errno; - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + /* + * We only want to process the interrupt here if socket writes are + * blocking to increase the chance to get an error message to the + * client. If we're not blocked there'll soon be a + * CHECK_FOR_INTERRUPTS(). But if we're blocked we'll never get out of + * that situation if the client has died. + */ + if (ProcDiePending && blocked) + { + /* + * We're dying. It's safe (and sane) to handle that now. But we don't + * want to send the client the error message as that a) would possibly + * block again b) would possibly lead to sending an error message to + * the client, while we already started to send something else. + */ + if (whereToSendOutput == DestRemote) + whereToSendOutput = DestNone; - errno = save_errno; + CHECK_FOR_INTERRUPTS(); } -} + errno = save_errno; +} /* * Do raw parsing (only). @@ -1957,7 +2015,9 @@ exec_bind_message(StringInfo input_message) * snapshot active till we're done, so that plancache.c doesn't have to * take new ones. */ - if (numParams > 0 || analyze_requires_snapshot(psrc->raw_parse_tree)) + if (numParams > 0 || + (psrc->raw_parse_tree && + analyze_requires_snapshot(psrc->raw_parse_tree))) { PushActiveSnapshot(GetTransactionSnapshot()); snapshot_set = true; @@ -1970,9 +2030,8 @@ exec_bind_message(StringInfo input_message) { int paramno; - /* sizeof(ParamListInfoData) includes the first array element */ - params = (ParamListInfo) palloc(sizeof(ParamListInfoData) + - (numParams - 1) * sizeof(ParamExternData)); + params = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) + + numParams * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ params->paramFetch = NULL; params->paramFetchArg = NULL; @@ -2410,7 +2469,7 @@ exec_execute_message(const char *portal_name, long max_rows) * check_log_statement * Determine whether command should be logged because of log_statement * - * parsetree_list can be either raw grammar output or a list of planned + * stmt_list can be either raw grammar output or a list of planned * statements */ static bool @@ -2997,23 +3056,6 @@ die(SIGNAL_ARGS) { InterruptPending = true; ProcDiePending = true; - - /* - * If it's safe to interrupt, and we're waiting for input or a lock, - * service the interrupt immediately - */ - if (ImmediateInterruptOK && InterruptHoldoffCount == 0 && - CritSectionCount == 0) - { - /* bump holdoff count to make ProcessInterrupts() a no-op */ - /* until we are done getting ready for it */ - InterruptHoldoffCount++; - LockErrorCleanup(); /* prevent CheckDeadLock from running */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); - InterruptHoldoffCount--; - ProcessInterrupts(); - } } #ifdef XCP @@ -3025,8 +3067,16 @@ die(SIGNAL_ARGS) #endif /* If we're still here, waken anything waiting on the process latch */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); + + /* + * If we're in single user mode, we want to quit immediately - we can't + * rely on latches as they wouldn't work when stdin/stdout is a + * file. Rather ugly, but it's unlikely to be worthwhile to invest much + * more effort just for the benefit of single user mode. + */ + if (DoingCommandRead && whereToSendOutput != DestRemote) + ProcessInterrupts(); errno = save_errno; } @@ -3048,28 +3098,10 @@ StatementCancelHandler(SIGNAL_ARGS) { InterruptPending = true; QueryCancelPending = true; - - /* - * If it's safe to interrupt, and we're waiting for input or a lock, - * service the interrupt immediately - */ - if (ImmediateInterruptOK && InterruptHoldoffCount == 0 && - CritSectionCount == 0) - { - /* bump holdoff count to make ProcessInterrupts() a no-op */ - /* until we are done getting ready for it */ - InterruptHoldoffCount++; - LockErrorCleanup(); /* prevent CheckDeadLock from running */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); - InterruptHoldoffCount--; - ProcessInterrupts(); - } } /* If we're still here, waken anything waiting on the process latch */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -3094,8 +3126,7 @@ SigHupHandler(SIGNAL_ARGS) int save_errno = errno; got_SIGHUP = true; - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -3207,23 +3238,6 @@ RecoveryConflictInterrupt(ProcSignalReason reason) */ if (reason == PROCSIG_RECOVERY_CONFLICT_DATABASE) RecoveryConflictRetryable = false; - - /* - * If it's safe to interrupt, and we're waiting for input or a lock, - * service the interrupt immediately - */ - if (ImmediateInterruptOK && InterruptHoldoffCount == 0 && - CritSectionCount == 0) - { - /* bump holdoff count to make ProcessInterrupts() a no-op */ - /* until we are done getting ready for it */ - InterruptHoldoffCount++; - LockErrorCleanup(); /* prevent CheckDeadLock from running */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); - InterruptHoldoffCount--; - ProcessInterrupts(); - } } /* @@ -3233,8 +3247,7 @@ RecoveryConflictInterrupt(ProcSignalReason reason) * waiting on that latch, expecting to get interrupted by query cancels et * al., would also need to set set_latch_on_sigusr1. */ - if (MyProc) - SetLatch(&MyProc->procLatch); + SetLatch(MyLatch); errno = save_errno; } @@ -3249,21 +3262,24 @@ RecoveryConflictInterrupt(ProcSignalReason reason) void ProcessInterrupts(void) { - /* OK to accept interrupt now? */ + /* OK to accept any interrupts now? */ if (InterruptHoldoffCount != 0 || CritSectionCount != 0) return; InterruptPending = false; + if (ProcDiePending) { ProcDiePending = false; QueryCancelPending = false; /* ProcDie trumps QueryCancel */ - ImmediateInterruptOK = false; /* not idle anymore */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); /* As in quickdie, don't risk sending to client during auth */ if (ClientAuthInProgress && whereToSendOutput == DestRemote) whereToSendOutput = DestNone; - if (IsAutoVacuumWorkerProcess()) + if (ClientAuthInProgress) + ereport(FATAL, + (errcode(ERRCODE_QUERY_CANCELED), + errmsg("canceling authentication due to timeout"))); + else if (IsAutoVacuumWorkerProcess()) ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating autovacuum process due to administrator command"))); @@ -3293,82 +3309,89 @@ ProcessInterrupts(void) if (ClientConnectionLost) { QueryCancelPending = false; /* lost connection trumps QueryCancel */ - ImmediateInterruptOK = false; /* not idle anymore */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); /* don't send to client, we already know the connection to be dead. */ whereToSendOutput = DestNone; ereport(FATAL, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("connection to client lost"))); } + + /* + * If a recovery conflict happens while we are waiting for input from the + * client, the client is presumably just sitting idle in a transaction, + * preventing recovery from making progress. Terminate the connection to + * dislodge it. + */ + if (RecoveryConflictPending && DoingCommandRead) + { + QueryCancelPending = false; /* this trumps QueryCancel */ + RecoveryConflictPending = false; + LockErrorCleanup(); + pgstat_report_recovery_conflict(RecoveryConflictReason); + ereport(FATAL, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + errmsg("terminating connection due to conflict with recovery"), + errdetail_recovery_conflict(), + errhint("In a moment you should be able to reconnect to the" + " database and repeat your command."))); + } + if (QueryCancelPending) { - QueryCancelPending = false; - if (ClientAuthInProgress) + /* + * Don't allow query cancel interrupts while reading input from the + * client, because we might lose sync in the FE/BE protocol. (Die + * interrupts are OK, because we won't read any further messages from + * the client in that case.) + */ + if (QueryCancelHoldoffCount != 0) { - ImmediateInterruptOK = false; /* not idle anymore */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); - /* As in quickdie, don't risk sending to client during auth */ - if (whereToSendOutput == DestRemote) - whereToSendOutput = DestNone; - ereport(ERROR, - (errcode(ERRCODE_QUERY_CANCELED), - errmsg("canceling authentication due to timeout"))); + /* + * Re-arm InterruptPending so that we process the cancel request + * as soon as we're done reading the message. + */ + InterruptPending = true; + return; } + QueryCancelPending = false; + /* * If LOCK_TIMEOUT and STATEMENT_TIMEOUT indicators are both set, we * prefer to report the former; but be sure to clear both. */ if (get_timeout_indicator(LOCK_TIMEOUT, true)) { - ImmediateInterruptOK = false; /* not idle anymore */ (void) get_timeout_indicator(STATEMENT_TIMEOUT, true); - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("canceling statement due to lock timeout"))); } if (get_timeout_indicator(STATEMENT_TIMEOUT, true)) { - ImmediateInterruptOK = false; /* not idle anymore */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to statement timeout"))); } if (IsAutoVacuumWorkerProcess()) { - ImmediateInterruptOK = false; /* not idle anymore */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling autovacuum task"))); } if (RecoveryConflictPending) { - ImmediateInterruptOK = false; /* not idle anymore */ RecoveryConflictPending = false; - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); pgstat_report_recovery_conflict(RecoveryConflictReason); - if (DoingCommandRead) - ereport(FATAL, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("terminating connection due to conflict with recovery"), - errdetail_recovery_conflict(), - errhint("In a moment you should be able to reconnect to the" - " database and repeat your command."))); - else - ereport(ERROR, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + ereport(ERROR, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("canceling statement due to conflict with recovery"), - errdetail_recovery_conflict())); + errdetail_recovery_conflict())); } /* @@ -3378,14 +3401,13 @@ ProcessInterrupts(void) */ if (!DoingCommandRead) { - ImmediateInterruptOK = false; /* not idle anymore */ - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); + LockErrorCleanup(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to user request"))); } } + /* If we get here, do nothing (probably, QueryCancelPending was reset) */ } @@ -3678,7 +3700,7 @@ get_stats_option_name(const char *arg) * argv[0] is ignored in either case (it's assumed to be the program name). * * ctx is PGC_POSTMASTER for secure options, PGC_BACKEND for insecure options - * coming from the client, or PGC_SUSET for insecure options coming from + * coming from the client, or PGC_SU_BACKEND for insecure options coming from * a superuser client. * * If a database name is present in the command line arguments, it's @@ -3731,14 +3753,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, * postmaster/postmaster.c (the option sets should not conflict) and with * the common help() function in main/main.c. */ - while ((flag = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) + while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) { switch (flag) { - case 'A': - SetConfigOption("debug_assertions", optarg, ctx, gucsource); - break; - case 'B': SetConfigOption("shared_buffers", optarg, ctx, gucsource); break; @@ -4031,30 +4049,12 @@ PostgresMain(int argc, char *argv[], cluster_ex_lock_held = false; #endif /* XCP */ - /* - * Initialize globals (already done if under postmaster, but not if - * standalone). - */ + /* Initialize startup process environment if necessary. */ if (!IsUnderPostmaster) - { - MyProcPid = getpid(); - - MyStartTime = time(NULL); - } + InitStandaloneProcess(argv[0]); SetProcessingMode(InitProcessing); - /* Compute paths, if we didn't inherit them from postmaster */ - if (my_exec_path[0] == '\0') - { - if (find_my_exec(argv[0], my_exec_path) < 0) - elog(FATAL, "%s: could not locate my own executable path", - argv[0]); - } - - if (pkglib_path[0] == '\0') - get_pkglib_path(my_exec_path, pkglib_path); - /* * Set default values for command-line options. */ @@ -4085,11 +4085,6 @@ PostgresMain(int argc, char *argv[], } /* - * You might expect to see a setsid() call here, but it's not needed, - * because if we are under a postmaster then BackendInitialize() did it. - */ - - /* * Set up signal handlers and masks. * * Note that postmaster blocked all signals before forking child process, @@ -4199,7 +4194,7 @@ PostgresMain(int argc, char *argv[], * it inside InitPostgres() instead. In particular, anything that * involves database access should be there, not here. */ - InitPostgres(dbname, InvalidOid, username, NULL); + InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL); /* * If the PostmasterContext is still around, recycle the space; we don't @@ -4396,14 +4391,8 @@ PostgresMain(int argc, char *argv[], disable_all_timeouts(false); QueryCancelPending = false; /* second to avoid race condition */ - /* - * Turn off these interrupts too. This is only needed here and not in - * other exception-catching places since these interrupts are only - * enabled while we wait for client input. - */ + /* Not reading from the client anymore. */ DoingCommandRead = false; - DisableNotifyInterrupt(); - DisableCatchupInterrupt(); /* Make sure libpq is in a good state */ pq_comm_reset(); @@ -4453,6 +4442,19 @@ PostgresMain(int argc, char *argv[], /* We don't have a transaction command open anymore */ xact_started = false; + /* + * If an error occurred while we were reading a message from the + * client, we have potentially lost track of where the previous + * message ends and the next one begins. Even though we have + * otherwise recovered from the error, we cannot safely read any more + * messages from the client, so there isn't much we can do with the + * connection anymore. + */ + if (pq_is_reading_msg()) + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("terminating connection because protocol sync was lost"))); + /* Now we can allow interrupts again */ RESUME_INTERRUPTS(); } @@ -4555,7 +4557,14 @@ PostgresMain(int argc, char *argv[], /* * (4) disable async signal conditions again. + * + * Query cancel is supposed to be a no-op when there is no query in + * progress, so if a query cancel arrived while we were idle, just + * reset QueryCancelPending. ProcessInterrupts() has that effect when + * it's called when DoingCommandRead is set, so check for interrupts + * before resetting DoingCommandRead. */ + CHECK_FOR_INTERRUPTS(); DoingCommandRead = false; /* |