diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
commit | d31084e9d1118b25fd16580d9d8c2924b5740dff (patch) | |
tree | 3179e66307d54df9c7b966543550e601eb55e668 /src/backend/utils/error | |
download | postgresql-d31084e9d1118b25fd16580d9d8c2924b5740dff.tar.gz postgresql-d31084e9d1118b25fd16580d9d8c2924b5740dff.zip |
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/utils/error')
-rw-r--r-- | src/backend/utils/error/Makefile.inc | 14 | ||||
-rw-r--r-- | src/backend/utils/error/assert.c | 64 | ||||
-rw-r--r-- | src/backend/utils/error/elog.c | 237 | ||||
-rw-r--r-- | src/backend/utils/error/exc.c | 183 | ||||
-rw-r--r-- | src/backend/utils/error/excabort.c | 28 | ||||
-rw-r--r-- | src/backend/utils/error/excid.c | 64 | ||||
-rw-r--r-- | src/backend/utils/error/format.c | 40 |
7 files changed, 630 insertions, 0 deletions
diff --git a/src/backend/utils/error/Makefile.inc b/src/backend/utils/error/Makefile.inc new file mode 100644 index 00000000000..2c3d469669b --- /dev/null +++ b/src/backend/utils/error/Makefile.inc @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------- +# +# Makefile.inc-- +# Makefile for utils/error +# +# Copyright (c) 1994, Regents of the University of California +# +# +# IDENTIFICATION +# $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ +# +#------------------------------------------------------------------------- + +SUBSRCS+= assert.c elog.c exc.c excabort.c excid.c format.c diff --git a/src/backend/utils/error/assert.c b/src/backend/utils/error/assert.c new file mode 100644 index 00000000000..ac2de1631d1 --- /dev/null +++ b/src/backend/utils/error/assert.c @@ -0,0 +1,64 @@ +/*------------------------------------------------------------------------- + * + * assert.c-- + * Assert code. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/error/assert.c,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ + * + * NOTE + * This should eventually work with elog(), dlog(), etc. + * + *------------------------------------------------------------------------- + */ +#include <stdio.h> + +#include "c.h" /* where the declaration goes */ +#include "utils/module.h" + +#include "utils/exc.h" + +int +ExceptionalCondition(char* conditionName, + Exception *exceptionP, + char* detail, + char* fileName, + int lineNumber) +{ + extern char* ExcFileName; /* XXX */ + extern Index ExcLineNumber; /* XXX */ + + ExcFileName = fileName; + ExcLineNumber = lineNumber; + + if (!PointerIsValid(conditionName) + || !PointerIsValid(fileName) + || !PointerIsValid(exceptionP)) { + fprintf(stderr, "ExceptionalCondition: bad arguments\n"); + + ExcAbort(exceptionP, + (ExcDetail)detail, + (ExcData)NULL, + (ExcMessage)NULL); + } else { + fprintf(stderr, + "%s(\"%s:%s\", File: \"%s\", Line: %d)\n", + exceptionP->message, conditionName, detail, + fileName, lineNumber); + } + + /* + * XXX Depending on the Exception and tracing conditions, you will + * XXX want to stop here immediately and maybe dump core. + * XXX This may be especially true for Assert(), etc. + */ + + /* TraceDump(); dump the trace stack */ + + /* XXX FIXME: detail is lost */ + ExcRaise(exceptionP, (ExcDetail)0, (ExcData)NULL, conditionName); + return(0); +} diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c new file mode 100644 index 00000000000..d5bef1ab1ba --- /dev/null +++ b/src/backend/utils/error/elog.c @@ -0,0 +1,237 @@ +/*------------------------------------------------------------------------- + * + * elog.c-- + * error logger + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#ifndef O_RDONLY +#include <sys/file.h> +#endif /* O_RDONLY */ +#include <sys/types.h> +#include <stdarg.h> +#include <errno.h> + +#include "postgres.h" +#include "miscadmin.h" +#include "utils/elog.h" +#include "libpq/libpq.h" +#include "storage/proc.h" + +static int Debugfile = -1; +static int Err_file = -1; +static int ElogDebugIndentLevel = 0; + +extern char OutputFileName[]; +#ifdef WIN32 +extern jmp_buf Warn_restart; +#endif + +/* + * elog -- + * Old error logging function. + */ +void +elog(int lev, char *fmt, ... ) +{ + va_list ap; + char buf[ELOG_MAXLEN], line[ELOG_MAXLEN]; + register char *bp, *cp; + extern int errno, sys_nerr; +#if !defined(PORTNAME_BSD44_derived) && !defined(PORTNAME_bsdi) + extern char *sys_errlist[]; +#endif /* !PORTNAME_BSD44_derived */ +#ifndef PG_STANDALONE + extern FILE *Pfout; +#endif /* !PG_STANDALONE */ + time_t tim, time(); + int len; + int i = 0; + + va_start(ap, fmt); + if (lev == DEBUG && Debugfile < 0) { + return; + } + switch (lev) { + case NOIND: + i = ElogDebugIndentLevel-1; + if (i < 0) i = 0; + if (i > 30) i = i%30; + cp = "DEBUG:"; + break; + case DEBUG: + i = ElogDebugIndentLevel; + if (i < 0) i = 0; + if (i > 30) i = i%30; + cp = "DEBUG:"; + break; + case NOTICE: + cp = "NOTICE:"; + break; + case WARN: + cp = "WARN:"; + break; + default: + sprintf(line, "FATAL %d:", lev); + cp = line; + } +#ifdef ELOG_TIMESTAMPS + time(&tim); + strcat(strcpy(buf, cp), ctime(&tim)+4); + bp = buf+strlen(buf)-6; + *bp++ = ':'; +#else + strcpy(buf,cp); + bp = buf+strlen(buf); +#endif + while (i-- >0) *bp++ = ' '; + for (cp = fmt; *cp; cp++) + if (*cp == '%' && *(cp+1) == 'm') { + if (errno < sys_nerr && errno >= 0) + strcpy(bp, sys_errlist[errno]); + else + sprintf(bp, "error %d", errno); + bp += strlen(bp); + cp++; + } else + *bp++ = *cp; + *bp = '\0'; + vsprintf(line, buf, ap); + va_end(ap); + len = strlen(strcat(line, "\n")); + if (Debugfile > -1) + write(Debugfile, line, len); + if (lev == DEBUG || lev == NOIND) + return; + + /* + * If there's an error log file other than our channel to the + * front-end program, write to it first. This is important + * because there's a bug in the socket code on ultrix. If the + * front end has gone away (so the channel to it has been closed + * at the other end), then writing here can cause this backend + * to exit without warning -- that is, write() does an exit(). + * In this case, our only hope of finding out what's going on + * is if Err_file was set to some disk log. This is a major pain. + */ + + if (Err_file > -1 && Debugfile != Err_file) { + if (write(Err_file, line, len) < 0) { + write(open("/dev/console", O_WRONLY, 0666), line, len); + fflush(stdout); + fflush(stderr); + exitpg(lev); + } + fsync(Err_file); + } + +#ifndef PG_STANDALONE + /* Send IPC message to the front-end program */ + if (Pfout != NULL && lev > DEBUG) { + /* notices are not exactly errors, handle it differently */ + if (lev == NOTICE) + pq_putnchar("N", 1); + else + pq_putnchar("E", 1); + /* pq_putint(-101, 4);*/ /* should be query id */ + pq_putstr(line); + pq_flush(); + } +#endif /* !PG_STANDALONE */ + + if (lev == WARN) { + ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ +#ifndef WIN32 + kill(getpid(), 1); /* abort to traffic cop */ + pause(); +#else + longjmp(Warn_restart, 1); +#endif /* WIN32 */ + /* + * The pause(3) is just to avoid race conditions where the + * thread of control on an MP system gets past here (i.e., + * the signal is not received instantaneously). + */ + } + + if (lev == FATAL) { + /* + * Assume that if we have detected the failure we can + * exit with a normal exit status. This will prevent + * the postmaster from cleaning up when it's not needed. + */ + fflush(stdout); + fflush(stderr); + ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ + ProcReleaseLocks(); /* get rid of real locks we hold */ + exitpg(0); + } + + if (lev > FATAL) { + fflush(stdout); + fflush(stderr); + exitpg(lev); + } +} + +#ifndef PG_STANDALONE +int +DebugFileOpen() +{ + int fd, istty; + + Err_file = Debugfile = -1; + ElogDebugIndentLevel = 0; + + if (OutputFileName[0]) { + OutputFileName[MAXPGPATH-1] = '\0'; + if ((fd = open(OutputFileName, O_CREAT|O_APPEND|O_WRONLY, + 0666)) < 0) + elog(FATAL, "DebugFileOpen: open of %s: %m", + OutputFileName); + istty = isatty(fd); + (void) close(fd); + /* If the file is a tty and we're running under the + * postmaster, try to send stdout there as well (if it + * isn't a tty then stderr will block out stdout, so we + * may as well let stdout go wherever it was going before). + */ + if (istty && + IsUnderPostmaster && + !freopen(OutputFileName, "a", stdout)) + elog(FATAL, "DebugFileOpen: %s reopen as stdout: %m", + OutputFileName); + if (!freopen(OutputFileName, "a", stderr)) + elog(FATAL, "DebugFileOpen: %s reopen as stderr: %m", + OutputFileName); + Err_file = Debugfile = fileno(stderr); + return(Debugfile); + } +#ifndef WIN32 + /* If no filename was specified, send debugging output to stderr. + * If stderr has been hosed, try to open a file. + */ + fd = fileno(stderr); + if (fcntl(fd, F_GETFD, 0) < 0) { + sprintf(OutputFileName, "%s/pg.errors.%d", + GetPGData(), getpid()); + fd = open(OutputFileName, O_CREAT|O_APPEND|O_WRONLY, 0666); + } +#endif /* WIN32 */ + if (fd < 0) + elog(FATAL, "DebugFileOpen: could not open debugging file"); + + Err_file = Debugfile = fd; + return(Debugfile); +} +#endif diff --git a/src/backend/utils/error/exc.c b/src/backend/utils/error/exc.c new file mode 100644 index 00000000000..35c5db9118f --- /dev/null +++ b/src/backend/utils/error/exc.c @@ -0,0 +1,183 @@ +/*------------------------------------------------------------------------- + * + * exc.c-- + * POSTGRES exception handling code. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/exc.c,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ + * + * NOTE + * XXX this code needs improvement--check for state violations and + * XXX reset after handling an exception. + * + *------------------------------------------------------------------------- + */ +#include <stdio.h> /* XXX use own I/O routines */ +#include <errno.h> +#include "utils/exc.h" +#include "storage/ipc.h" + +/* + * Global Variables + */ +static bool ExceptionHandlingEnabled = false; + +char* ExcFileName = NULL; +Index ExcLineNumber = 0; + +ExcFrame *ExcCurFrameP = NULL; + +static ExcProc *ExcUnCaughtP = NULL; + +extern char* ProgramName; + +/* + * Exported Functions + */ + +/* + * EnableExceptionHandling -- + * Enables/disables the exception handling system. + * + * Note: + * This must be called before any exceptions occur. I.e., call this first! + * This routine will not return if an error is detected. + * This does not follow the usual Enable... protocol. + * This should be merged more closely with the error logging and tracing + * packages. + * + * Exceptions: + * none + */ +/* + * Excection handling should be supported by the language, thus there should + * be no need to explicitly enable exception processing. + * + * This function should probably not be called, ever. Currently it does + * almost nothing. If there is a need for this intialization and checking. + * then this function should be converted to the new-style Enable code and + * called by all the other module Enable functions. + */ +void +EnableExceptionHandling(bool on) +{ + if (on == ExceptionHandlingEnabled) { + /* XXX add logging of failed state */ + exitpg(255); + /* ExitPostgres(FatalExitStatus); */ + } + + if (on) { /* initialize */ + ; + } else { /* cleanup */ + ExcFileName = NULL; + ExcLineNumber = 0; + ExcCurFrameP = NULL; + ExcUnCaughtP = NULL; + } + + ExceptionHandlingEnabled = on; +} + +void +ExcPrint(Exception *excP, + ExcDetail detail, + ExcData data, + ExcMessage message) +{ + extern int errno; + extern int sys_nerr; +#if !defined(PORTNAME_BSD44_derived) && !defined(PORTNAME_bsdi) + extern char *sys_errlist[]; +#endif /* !PORTNAME_BSD44_derived */ + +#ifdef lint + data = data; +#endif + + (void) fflush(stdout); /* In case stderr is buffered */ + +#if 0 + if (ProgramName != NULL && *ProgramName != '\0') + (void) fprintf(stderr, "%s: ", ProgramName); +#endif + + if (message != NULL) + (void) fprintf(stderr, "%s", message); + else if (excP->message != NULL) + (void) fprintf(stderr, "%s", excP->message); + else +#ifdef lint + (void) fprintf(stderr, "UNNAMED EXCEPTION 0x%lx", excP); +#else + (void) fprintf(stderr, "UNNAMED EXCEPTION 0x%lx", (long)excP); +#endif + + (void) fprintf(stderr, " (%ld)", detail); + + if (errno > 0 && errno < sys_nerr && + sys_errlist[errno] != NULL && sys_errlist[errno][0] != '\0') + (void) fprintf(stderr, " [%s]", sys_errlist[errno]); + else if (errno != 0) + (void) fprintf(stderr, " [Error %d]", errno); + + (void) fprintf(stderr, "\n"); + + (void) fflush(stderr); +} + +ExcProc * +ExcGetUnCaught() +{ + return (ExcUnCaughtP); +} + +ExcProc * +ExcSetUnCaught(ExcProc *newP) +{ + ExcProc *oldP = ExcUnCaughtP; + + ExcUnCaughtP = newP; + + return (oldP); +} + +void +ExcUnCaught(Exception *excP, + ExcDetail detail, + ExcData data, + ExcMessage message) +{ + ExcPrint(excP, detail, data, message); + + ExcAbort(excP, detail, data, message); +} + +void +ExcRaise(Exception *excP, + ExcDetail detail, + ExcData data, + ExcMessage message) +{ + register ExcFrame *efp; + + efp = ExcCurFrameP; + if (efp == NULL) { + if (ExcUnCaughtP != NULL) + (*ExcUnCaughtP)(excP, detail, data, message); + + ExcUnCaught(excP, detail, data, message); + } else { + efp->id = excP; + efp->detail = detail; + efp->data = data; + efp->message = message; + + ExcCurFrameP = efp->link; + + longjmp(efp->context, 1); + } +} diff --git a/src/backend/utils/error/excabort.c b/src/backend/utils/error/excabort.c new file mode 100644 index 00000000000..d1b14361ea5 --- /dev/null +++ b/src/backend/utils/error/excabort.c @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * excabort.c-- + * Default exception abort code. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/excabort.c,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#include "utils/exc.h" /* where function declarations go */ + +void +ExcAbort(const Exception *excP, + ExcDetail detail, + ExcData data, + ExcMessage message) +{ +#ifdef __SABER__ + saber_stop(); +#else + /* dump core */ + abort(); +#endif +} diff --git a/src/backend/utils/error/excid.c b/src/backend/utils/error/excid.c new file mode 100644 index 00000000000..4d87c16344f --- /dev/null +++ b/src/backend/utils/error/excid.c @@ -0,0 +1,64 @@ +/*------------------------------------------------------------------------- + * + * excid.c-- + * POSTGRES known exception identifier code. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/excid.c,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#include "utils/excid.h" + +/***************************************************************************** + * Generic Recoverable Exceptions * + *****************************************************************************/ + + +/* + * FailedAssertion -- + * Indicates an Assert(...) failed. + */ +Exception FailedAssertion = { "Failed Assertion" }; + +/* + * BadState -- + * Indicates a function call request is inconsistent with module state. + */ +Exception BadState = { "Bad State for Function Call" }; + +/* + * BadArg -- + * Indicates a function call argument or arguments is out-of-bounds. + */ +Exception BadArg = { "Bad Argument to Function Call" }; + +/***************************************************************************** + * Specific Recoverable Exceptions * + *****************************************************************************/ + +/* + * BadAllocSize -- + * Indicates that an allocation request is of unreasonable size. + */ +Exception BadAllocSize = { "Too Large Allocation Request" }; + +/* + * ExhaustedMemory -- + * Indicates an dynamic memory allocation failed. + */ +Exception ExhaustedMemory = { "Memory Allocation Failed" }; + +/* + * Unimplemented -- + * Indicates a function call request requires unimplemented code. + */ +Exception Unimplemented = { "Unimplemented Functionality" }; + +Exception CatalogFailure = {"Catalog failure"}; /* XXX inconsistent */ +Exception InternalError = {"Internal Error"}; /* XXX inconsistent */ +Exception SemanticError = {"Semantic Error"}; /* XXX inconsistent */ +Exception SystemError = {"System Error"}; /* XXX inconsistent */ diff --git a/src/backend/utils/error/format.c b/src/backend/utils/error/format.c new file mode 100644 index 00000000000..99a5d15af57 --- /dev/null +++ b/src/backend/utils/error/format.c @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------------- + * + * format.c-- + * a wrapper around code that does what vsprintf does. + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/utils/error/Attic/format.c,v 1.1.1.1 1996/07/09 06:22:07 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#include <stdio.h> +#include <stdarg.h> +#include "c.h" + +#define FormMaxSize 1024 +#define FormMinSize (FormMaxSize / 8) + +static char FormBuf[FormMaxSize]; + + +/* ---------------- + * form + * ---------------- + */ +char * +form(char *fmt, ... ) +{ + va_list args; + + va_start(args, fmt); + + (void) vsprintf(FormBuf, fmt, args); + + va_end(args); + + return (FormBuf); +} |