diff options
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 226 |
1 files changed, 126 insertions, 100 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 2a3e7e77300..29486bd6f39 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.130 1999/09/29 16:06:10 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.131 1999/10/06 21:58:08 vadim Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -58,6 +58,7 @@ #include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "tcop/utility.h" +#include "storage/proc.h" #include "utils/ps_status.h" #include "utils/temprel.h" #include "utils/trace.h" @@ -98,11 +99,20 @@ */ /*static bool EnableRewrite = true; , never changes why have it*/ -CommandDest whereToSendOutput; +CommandDest whereToSendOutput = Debug; /* Define status buffer needed by PS_SET_STATUS */ PS_DEFINE_BUFFER; +extern void BaseInit(void); +extern void StartupXLOG(void); +extern void ShutdownXLOG(void); + +extern void HandleDeadLock(SIGNAL_ARGS); + +extern char XLogDir[]; +extern char ControlFilePath[]; + extern int lockingOff; extern int NBuffers; @@ -115,21 +125,8 @@ char relname[80]; /* current relation name */ /* note: these declarations had better match tcopprot.h */ DLLIMPORT sigjmp_buf Warn_restart; -bool InError = true; - -/* - * Note: InError is a flag to elog() telling whether it is safe to longjmp - * back to PostgresMain. It is "false", allowing an error longjmp, during - * normal processing. It is "true" during startup, when we have not yet - * set the Warn_restart jmp_buf, and also "true" in the interval when we - * have executed a longjmp back to PostgresMain and not yet finished cleaning - * up after the error. In either case, elog(ERROR) should be treated as a - * fatal exit condition rather than attempting to recover --- since there is - * noplace to recover to in the first case, and we don't want to risk an - * infinite loop of "error recoveries" in the second case. - * - * Therefore, InError starts out "true" at program load time, as shown above. - */ +bool InError = false; +bool ExitAfterAbort = false; extern int NBuffers; @@ -773,6 +770,7 @@ handle_warn(SIGNAL_ARGS) void quickdie(SIGNAL_ARGS) { + PG_SETMASK(&BlockSig); elog(NOTICE, "Message from PostgreSQL backend:" "\n\tThe Postmaster has informed me that some other backend" " died abnormally and possibly corrupted shared memory." @@ -787,13 +785,25 @@ quickdie(SIGNAL_ARGS) * storage. Just nail the windows shut and get out of town. */ - exit(0); + exit(1); } +/* + * Abort transaction and exit + */ void die(SIGNAL_ARGS) { - ExitPostgres(0); + PG_SETMASK(&BlockSig); + /* + * If ERROR/FATAL is in progress... + */ + if (InError) + { + ExitAfterAbort = true; + return; + } + elog(FATAL, "The system is shutting down"); } /* signal handler for floating point exception */ @@ -907,6 +917,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) #endif DataDir = getenv("PGDATA"); + SetProcessingMode(InitProcessing); + /* * Try to get initial values for date styles and formats. Does not do * a complete job, but should be good enough for backend. Cannot call @@ -1265,10 +1277,68 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) break; } - /* ---------------- - * get user name (needed now in case it is the default database name) - * and check command line validity - * ---------------- + if (ShowStats && + (ShowParserStats || ShowPlannerStats || ShowExecutorStats)) + { + fprintf(stderr, "-s can not be used together with -t.\n"); + proc_exit(1); + } + + if (!DataDir) + { + fprintf(stderr, "%s does not know where to find the database system " + "data. You must specify the directory that contains the " + "database system either by specifying the -D invocation " + "option or by setting the PGDATA environment variable.\n\n", + argv[0]); + proc_exit(1); + } + + /* + * 1. Set BlockSig and UnBlockSig masks. + * 2. Set up signal handlers. + * 3. Allow only SIGUSR1 signal (we never block it) + * during initialization. + * + * Note that postmaster already blocked ALL signals to make us happy. + */ + if (!IsUnderPostmaster) + { + PG_INITMASK(); + PG_SETMASK(&BlockSig); + } + +#ifdef HAVE_SIGPROCMASK + sigdelset(&BlockSig, SIGUSR1); +#else + BlockSig &= ~(sigmask(SIGUSR1)); +#endif + + pqsignal(SIGHUP, read_pg_options); /* update pg_options from file */ + pqsignal(SIGINT, QueryCancelHandler); /* cancel current query */ + pqsignal(SIGQUIT, handle_warn); /* handle error */ + pqsignal(SIGTERM, die); + pqsignal(SIGALRM, HandleDeadLock); + /* + * Ignore failure to write to frontend. Note: if frontend closes + * connection, we will notice it and exit cleanly when control next + * returns to outer loop. This seems safer than forcing exit in the + * midst of output during who-knows-what operation... + */ + pqsignal(SIGPIPE, SIG_IGN); + pqsignal(SIGUSR1, quickdie); + pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */ + pqsignal(SIGFPE, FloatExceptionHandler); + pqsignal(SIGCHLD, SIG_IGN); /* ignored, sent by LockOwners */ + pqsignal(SIGTTIN, SIG_DFL); + pqsignal(SIGTTOU, SIG_DFL); + pqsignal(SIGCONT, SIG_DFL); + + PG_SETMASK(&BlockSig); /* block everything except SIGUSR1 */ + + /* + * Get user name (needed now in case it is the default database name) + * and check command line validity */ SetPgUserName(); userName = GetPgUserName(); @@ -1281,10 +1351,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) usage(argv[0]); proc_exit(1); } + pq_init(); /* initialize libpq at backend startup */ + whereToSendOutput = Remote; + BaseInit(); } else { /* interactive case: database name can be last arg on command line */ + whereToSendOutput = Debug; if (errs || argc - optind > 1) { usage(argv[0]); @@ -1298,23 +1372,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) argv[0]); proc_exit(1); } - } - - if (ShowStats && - (ShowParserStats || ShowPlannerStats || ShowExecutorStats)) - { - fprintf(stderr, "-s can not be used together with -t.\n"); - proc_exit(1); - } - - if (!DataDir) - { - fprintf(stderr, "%s does not know where to find the database system " - "data. You must specify the directory that contains the " - "database system either by specifying the -D invocation " - "option or by setting the PGDATA environment variable.\n\n", - argv[0]); - proc_exit(1); + BaseInit(); + sprintf(XLogDir, "%s%cpg_xlog", DataDir, SEP_CHAR); + sprintf(ControlFilePath, "%s%cpg_control", DataDir, SEP_CHAR); + StartupXLOG(); } /* @@ -1367,19 +1428,15 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) remote_info = remote_host = "unknown"; break; } - } - - /* ---------------- - * set process params for ps - * ---------------- - */ - if (IsUnderPostmaster) - { + /* + * Set process params for ps + */ PS_INIT_STATUS(real_argc, real_argv, argv[0], remote_info, userName, DBName); PS_SET_STATUS("startup"); } + /* ---------------- * print flags * ---------------- @@ -1409,23 +1466,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) } } - /* ---------------- - * initialize I/O - * ---------------- - */ - if (IsUnderPostmaster) - { - pq_init(); /* initialize libpq at backend startup */ - whereToSendOutput = Remote; - } - else - whereToSendOutput = Debug; - /* ---------------- - * general initialization - * ---------------- + /* + * general initialization */ - SetProcessingMode(InitProcessing); if (Verbose) TPRINTF(TRACE_VERBOSE, "InitPostgres"); @@ -1445,30 +1489,9 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) parser_input = makeStringInfo(); /* initialize input buffer */ - /* ---------------- - * Set up handler for cancel-request signal, and - * send this backend's cancellation info to the frontend. - * This should not be done until we are sure startup is successful. - * ---------------- - */ - - pqsignal(SIGHUP, read_pg_options); /* update pg_options from file */ - pqsignal(SIGINT, QueryCancelHandler); /* cancel current query */ - pqsignal(SIGQUIT, handle_warn); /* handle error */ - pqsignal(SIGTERM, die); - pqsignal(SIGPIPE, SIG_IGN); /* ignore failure to write to frontend */ - - /* - * Note: if frontend closes connection, we will notice it and exit - * cleanly when control next returns to outer loop. This seems safer - * than forcing exit in the midst of output during who-knows-what - * operation... + /* + * Send this backend's cancellation info to the frontend. */ - pqsignal(SIGUSR1, quickdie); - pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */ - pqsignal(SIGCHLD, SIG_IGN); /* ignored, sent by LockOwners */ - pqsignal(SIGFPE, FloatExceptionHandler); - if (whereToSendOutput == Remote && PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { @@ -1485,40 +1508,41 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.130 $ $Date: 1999/09/29 16:06:10 $\n"); + puts("$Revision: 1.131 $ $Date: 1999/10/06 21:58:08 $\n"); } - /* ---------------- + /* * Initialize the deferred trigger manager - * ---------------- */ if (DeferredTriggerInit() != 0) ExitPostgres(1); - /* ---------------- - * POSTGRES main processing loop begins here - * - * if an exception is encountered, processing resumes here - * so we abort the current transaction and start a new one. + /* + * POSTGRES main processing loop begins here * - * Note: elog(ERROR) does a siglongjmp() to transfer control here. - * See comments with the declaration of InError, above. - * ---------------- + * If an exception is encountered, processing resumes here + * so we abort the current transaction and start a new one. */ + SetProcessingMode(NormalProcessing); + if (sigsetjmp(Warn_restart, 1) != 0) { - InError = true; - time(&tim); if (Verbose) TPRINTF(TRACE_VERBOSE, "AbortCurrentTransaction"); AbortCurrentTransaction(); + InError = false; + if (ExitAfterAbort) + { + ProcReleaseLocks(); /* Just to be sure... */ + ExitPostgres(0); + } } - InError = false; + PG_SETMASK(&UnBlockSig); /* * Non-error queries loop here. @@ -1636,6 +1660,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) */ case 'X': case EOF: + if (!IsUnderPostmaster) + ShutdownXLOG(); pq_close(); proc_exit(0); break; |