summaryrefslogtreecommitdiff
path: root/sal/osl/os2/except.c
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/os2/except.c')
-rw-r--r--sal/osl/os2/except.c1061
1 files changed, 0 insertions, 1061 deletions
diff --git a/sal/osl/os2/except.c b/sal/osl/os2/except.c
deleted file mode 100644
index 5683aa21c..000000000
--- a/sal/osl/os2/except.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-/*
- *@@sourcefile except.c:
- * this file contains powerful exception handlers.
- * except.h also defines easy-to-use macros for them.
- *
- * Usage: All OS/2 programs, PM or text mode.
- *
- * <B>Introduction</B>
- *
- * OS/2 exception handlers are a mess to program and,
- * if installed wrongly, almost impossible to debug.
- * The problem is that for any program that does a bit
- * more than showing a message box, using exception
- * handlers is a must to avoid system hangs. This
- * especially applies to multi-thread programs using
- * mutex semaphores (more on that below). The functions
- * and macros in here are designed to make that more
- * simple.
- *
- * The macros in except.h automatically insert code for
- * properly registering and deregistering the handlers
- * in except.c. You should ALWAYS use these macros
- * instead of directly registering the handlers to avoid
- * accidentally forgetting to deregister them. If you
- * forget to deregister an exception handler, this can
- * lead to really strange errors (crashes, hangs) which
- * are nearly impossible to debug because the thread's
- * stack probably got completely messed up.
- *
- * The general idea of these macros is to define
- * TRY / CATCH blocks similar to C++. If an exception
- * occurs in the TRY block, execution is transferred to
- * the CATCH block. (This works in both C and C++, by the
- * way.)
- *
- * The "OnKill" function that was added with V0.9.0 has
- * been removed again with V0.9.7.
- *
- * The general usage is like this:
- *
- + int your_protected_func(int ...)
- + {
- + TRY_LOUD(excptid) // or: TRY_QUIET(excptid)
- + {
- + char *p = NULL;
- +
- + .... // the stuff in here is protected by
- + // the excHandlerLoud or excHandlerQuiet
- + // exception handler
- + *p = "A";
- + }
- + CATCH(excptid)
- + {
- + .... // exception occurred: react here
- + } END_CATCH(); // always needed!
- + } // end of your_func
- *
- * TRY_LOUD is for installing excHandlerLoud.
- * TRY_QUIET is for installing excHandlerQuiet.
- * CATCH / END_CATCH are the same for the two. This
- * is where the exception handler jumps to if an
- * exception occurs.
- * The CATCH block is _required_ even if you do nothing
- * in there, because the CATCH() macro will deregister
- * the handler.
- *
- * "excptid" can be any C identifier which is not used in
- * your current variable scope, e.g. "excpt1". This
- * is used for creating an EXCEPTSTRUCT variable of
- * that name on the stack. The "excptid"'s in TRY_* and
- * CATCH must match, since this is where the macros
- * store the exception handler data.
- *
- * These macros may be nested if you use different
- * "excptid"'s for sub-macros.
- *
- * Inside the TRY and CATCH blocks, you must not use
- * "goto" (to a location outside the block) or "return",
- * because this will not deregister the handler.
- *
- * Keep in mind that all the code in the TRY_* block is
- * protected by the handler, including all functions that
- * get called. So if you enclose your main() code in a
- * TRY_* block, your entire application is protected.
- * If any subfunction fails, execution is transferred to
- * the closest CATCH() that was installed (as with C++
- * try and catch).
- *
- * <B>Asynchronous exceptions</B>
- *
- * The exception handlers in this file (which are installed
- * with the TRY/CATCH mechanism) only intercept synchronous
- * exceptions, most importantly, XCPT_ACCESS_VIOLATION (see
- * excHandlerLoud for a list). They do not protect your code
- * against asynchronous exceptions.
- *
- * OS/2 defines asynchronous exceptions to be those that
- * can be delayed. With OS/2, there are only three of these:
- *
- * -- XCPT_PROCESS_TERMINATE
- * -- XCPT_ASYNC_PROCESS_TERMINATE
- * -- XCPT_SIGNAL (thread 1 only)
- *
- * To protect yourself against these also, put the section
- * in question in a DosEnterMustComplete/DosExitMustComplete
- * block as well.
- *
- * <B>Mutex semaphores</B>
- *
- * The problem with OS/2 mutex semaphores is that they are
- * sometimes not automatically released when a thread terminates.
- * If there are several mutexes involved and they are released
- * in improper order, you can get zombie threads on exit.
- * Even worse, if this happens to a PM thread, this will hang
- * the system.
- *
- * As a result, you should protect any section of code which
- * requests a semaphore with the exception handlers.
- *
- * So _whenever_ you request a mutex semaphore, enclose
- * the block with TRY/CATCH in case the code crashes.
- * Besides, enclose the TRY/CATCH block in a must-complete
- * section, like this:
- *
- + HMTX hmtx = ...
- +
- + int your_func(int)
- + {
- + BOOL fSemOwned = FALSE;
- +
- + TRY_QUIET(excpt1) // or TRY_LOUD
- + {
- + if (fSemOwned = !DosRequestMutexSem(hmtx, ...))
- + { ... // work on your protected data
- + }
- + // mutex gets released below
- + }
- + CATCH(excpt1) { } END_CATCH(); // always needed!
- +
- + if (fSemOwned)
- + // this gets executed always, even if an exception occurred
- + DosReleaseMutexSem(hmtx);
- + } // end of your_func
- *
- * This way your mutex semaphore gets released in every
- * possible condition.
- *
- * <B>Customizing</B>
- *
- * As opposed to versions before 0.9.0, this code is now
- * completely independent of XWorkplace. This file now
- * contains "pure" exception handlers only.
- *
- * However, you can customize these exception handlers by
- * calling excRegisterHooks. This is what XWorkplace does now.
- * This should be done upon initialization of your application.
- * If excRegisterHooks is not called, the following safe
- * defaults are used:
- *
- * -- the trap log file is TRAP.LOG in the root
- * directory of your boot drive.
- *
- * For details on the provided exception handlers, refer
- * to excHandlerLoud and excHandlerQuiet.
- *
- * More useful debug information can be found in the "OS/2 Debugging
- * Handbook", which is now available in INF format on the IBM
- * DevCon site ("http://service2.boulder.ibm.com/devcon/").
- * This book shows worked examples of how to unwind a stack dump.
- *
- * This file incorporates code from the following:
- * -- Monte Copeland, IBM Boca Ration, Florida, USA (1993)
- * -- Roman Stangl, from the Program Commander/2 sources
- * (1997-98)
- * -- Marc Fiammante, John Currier, Kim Rasmussen,
- * Anthony Cruise (EXCEPT3.ZIP package for a generic
- * exception handling DLL, available at Hobbes).
- *
- * If not explicitly stated otherwise, the code has been written
- * by me, Ulrich M�ller.
- *
- * Note: Version numbering in this file relates to XWorkplace version
- * numbering.
- *
- *@@header "helpers\except.h"
- */
-
-/*
- * This file Copyright (C) 1992-99 Ulrich M�ller,
- * Monte Copeland,
- * Roman Stangl,
- * Kim Rasmussen,
- * Marc Fiammante,
- * John Currier,
- * Anthony Cruise.
- * This file is part of the "XWorkplace helpers" source package.
- *
- * 2009-06-15 published under LGPL3 with Ulrich M�ller permission.
- *
- */
-
-#define OS2EMX_PLAIN_CHAR
- // this is needed for "os2emx.h"; if this is defined,
- // emx will define PSZ as _signed_ char, otherwise
- // as unsigned char
-
-#define INCL_DOSMODULEMGR
-#define INCL_DOSEXCEPTIONS
-#define INCL_DOSPROCESS
-#define INCL_DOSMISC
-#define INCL_DOSERRORS
-#include <os2.h>
-
-// C library headers
-#include <stdio.h> // needed for except.h
-#include <stdlib.h>
-#include <time.h>
-#include <string.h>
-#include <setjmp.h> // needed for except.h
-#include <assert.h> // needed for except.h
-
-#define DONT_REPLACE_MALLOC
-#include "helpers\setup.h" // code generation and debugging options
-
-// headers in /helpers
-#include "helpers\dosh.h" // Control Program helper routines
-#include "helpers\except.h" // exception handling
-#include "helpers\debug.h" // symbol/debug code analysis
-
-#pragma hdrstop
-
-/* ******************************************************************
- *
- * Global variables
- *
- ********************************************************************/
-
-// hooks to be registered using excRegisterHooks
-PFNEXCOPENFILE G_pfnExcOpenFile = 0;
-PFNEXCHOOK G_pfnExcHook = 0;
-PFNEXCHOOKERROR G_pfnExcHookError = 0;
-// beep flag for excHandlerLoud
-BOOL G_fBeepOnException = TRUE;
-
-ULONG G_ulExplainExceptionRunning = 0;
- // global flag which is != 0 if some exception handler
- // is inside excExplainException, so that XShutdown can
- // wait until the trap log is done;
- // this is exported thru except.h
- // V0.9.13 (2001-06-19) [umoeller]
-
-/*
- *@@category: Helpers\Control program helpers\Exceptions/debugging
- * See except.c.
- */
-
-/* ******************************************************************
- *
- * Exception helper routines
- *
- ********************************************************************/
-
-/*
- *@@ excDescribePage:
- *
- */
-
-VOID excDescribePage(FILE *file, ULONG ulCheck)
-{
- APIRET arc;
- ULONG ulCountPages = 1;
- ULONG ulFlagsPage = 0;
- arc = DosQueryMem((PVOID)ulCheck, &ulCountPages, &ulFlagsPage);
-
- if (arc == NO_ERROR)
- {
- fprintf(file, "valid, flags: ");
- if (ulFlagsPage & PAG_READ)
- fprintf(file, "read ");
- if (ulFlagsPage & PAG_WRITE)
- fprintf(file, "write ");
- if (ulFlagsPage & PAG_EXECUTE)
- fprintf(file, "execute ");
- if (ulFlagsPage & PAG_GUARD)
- fprintf(file, "guard ");
- if (ulFlagsPage & PAG_COMMIT)
- fprintf(file, "committed ");
- if (ulFlagsPage & PAG_SHARED)
- fprintf(file, "shared ");
- if (ulFlagsPage & PAG_FREE)
- fprintf(file, "free ");
- if (ulFlagsPage & PAG_BASE)
- fprintf(file, "base ");
- }
- else if (arc == ERROR_INVALID_ADDRESS)
- fprintf(file, "invalid");
-}
-
-/*
- *@@ excPrintStackFrame:
- * wrapper for dbgPrintStackFrame to format
- * output stuff right.
- *
- *@@added V0.9.2 (2000-03-10) [umoeller]
- *@@changed V0.9.12 (2001-05-12) [umoeller]: added seg:ofs to output always
- */
-
-VOID excPrintStackFrame(FILE *file, // in: output log file
- PSZ pszDescription, // in: description for stack frame (should be eight chars)
- ULONG ulAddress) // in: address to debug
-{
- APIRET arc = NO_ERROR;
- HMODULE hmod1 = NULLHANDLE;
- CHAR szMod1[2*CCHMAXPATH] = "unknown";
- ULONG ulObject = 0,
- ulOffset = 0;
- fprintf(file,
- " %-8s: %08lX ",
- pszDescription,
- ulAddress);
- arc = DosQueryModFromEIP(&hmod1,
- &ulObject,
- sizeof(szMod1), szMod1,
- &ulOffset,
- ulAddress);
-
- if (arc != NO_ERROR)
- {
- // error:
- fprintf(file,
- " %-8s Error: DosQueryModFromEIP returned %lu\n",
- szMod1,
- arc);
- }
- else
- {
- CHAR szFullName[2*CCHMAXPATH];
-
- fprintf(file,
- " %-8s %02lX:%08lX\n ",
- szMod1,
- ulObject + 1, // V0.9.12 (2001-05-12) [umoeller]
- ulOffset); // V0.9.12 (2001-05-12) [umoeller]
-
- DosQueryModuleName(hmod1, sizeof(szFullName), szFullName);
- dbgPrintStackFrame(file,
- szFullName,
- ulObject,
- ulOffset);
-
- fprintf(file, "\n");
-
- // make a 'tick' sound to let the user know we're still alive
- DosBeep(2000, 10);
- }
-}
-
-/*
- *@@ excDumpStackFrames:
- * called from excExplainException to dump the
- * thread's stack frames. This calls excPrintStackFrame
- * for each stack frame found.
- *
- *@@added V0.9.4 (2000-06-15) [umoeller]
- */
-
-VOID excDumpStackFrames(FILE *file, // in: logfile from fopen()
- PTIB ptib,
- PCONTEXTRECORD pContextRec) // in: excpt info
-{
- PULONG pulStackWord = 0;
-
- fprintf(file, "\n\nStack frames:\n Address Module seg:ofs\n");
-
- // first the trapping address itself
- excPrintStackFrame(file,
- "CS:EIP ",
- pContextRec->ctx_RegEip);
-
-
- pulStackWord = (PULONG)pContextRec->ctx_RegEbp;
- /* if (pContextRec->ctx_RegEbp < pContextRec->ctx_RegEsp)
- pulStackWord = (PULONG)(pContextRec->ctx_RegEbp & 0xFFFFFFF0);
- else
- pulStackWord = (PULONG)(pContextRec->ctx_RegEsp & 0xFFFFFFF0); */
-
- while ( (pulStackWord != 0)
- && (pulStackWord < (PULONG)ptib->tib_pstacklimit)
- )
- {
- CHAR szAddress[20];
-
- if (((ULONG)pulStackWord & 0x00000FFF) == 0x00000000)
- {
- // we're on a page boundary: check access
- ULONG ulCountPages = 0x1000;
- ULONG ulFlagsPage = 0;
- APIRET arc = DosQueryMem((void *)pulStackWord,
- &ulCountPages,
- &ulFlagsPage);
- if ( (arc != NO_ERROR)
- || ( (arc == NO_ERROR)
- && ( !( ((ulFlagsPage & (PAG_COMMIT|PAG_READ))
- == (PAG_COMMIT|PAG_READ)
- )
- )
- )
- )
- )
- {
- fprintf(file, "\n %08lX: ", (ULONG)pulStackWord);
- fprintf(file, "Page inaccessible");
- pulStackWord += 0x1000;
- continue; // for
- }
- }
-
- sprintf(szAddress, "%08lX",
- (ULONG)pulStackWord);
- excPrintStackFrame(file,
- szAddress,
- *(pulStackWord+1));
- pulStackWord = (PULONG)*(pulStackWord);
-
- if (pulStackWord == 0)
- fprintf(file, "\n pulStackWord == 0");
- else if (pulStackWord >= (PULONG)ptib->tib_pstacklimit)
- fprintf(file, "\n pulStackWord >= (PULONG)ptib->tib_pstacklimit");
- } // end while
-}
-
-/*
- *@@ excExplainException:
- * used by the exception handlers below to write
- * LOTS of information about the exception into a logfile.
- *
- * This calls excPrintStackFrame for each stack frame.
- *
- *@@changed V0.9.0 [umoeller]: added support for application hook
- *@@changed V0.9.0 (99-11-02) [umoeller]: added TID to dump
- *@@changed V0.9.2 (2000-03-10) [umoeller]: now using excPrintStackFrame
- *@@changed V0.9.3 (2000-05-03) [umoeller]: fixed crashes
- *@@changed V0.9.6 (2000-11-06) [umoeller]: added more register dumps
- *@@changed V0.9.13 (2001-06-19) [umoeller]: added global flag for whether this is running
- *@@changed V0.9.16 (2001-11-02) [pr]: make object display signed
- *@@changed V0.9.19 (2002-03-28) [umoeller]: added thread ordinal
- */
-
-VOID excExplainException(FILE *file, // in: logfile from fopen()
- PSZ pszHandlerName, // in: descriptive string
- PEXCEPTIONREPORTRECORD pReportRec, // in: excpt info
- PCONTEXTRECORD pContextRec) // in: excpt info
-{
- ULONG aulBuf[3];
- const char *pcszVersion = "unknown";
-
- PTIB ptib = NULL;
- PPIB ppib = NULL;
- HMODULE hMod1, hMod2;
- CHAR szMod1[CCHMAXPATH] = "unknown",
- szMod2[CCHMAXPATH] = "unknown";
- ULONG ulObjNum,
- ulOffset;
- ULONG ul;
-
- ULONG ulOldPriority = 0x0100; // regular, delta 0
-
- // raise global flag for whether this func is running
- // V0.9.13 (2001-06-19) [umoeller]
- G_ulExplainExceptionRunning++;
-
- // raise this thread's priority, because this
- // might take some time
- if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR)
- if (ptib)
- if (ptib->tib_ptib2)
- {
- ulOldPriority = ptib->tib_ptib2->tib2_ulpri;
- DosSetPriority(PRTYS_THREAD,
- PRTYC_REGULAR,
- PRTYD_MAXIMUM,
- 0); // current thread
- }
-
- // make some noise
-#ifndef __NOEXCEPTIONBEEPS__ // V0.9.19 (2002-04-17) [umoeller]
- if (G_fBeepOnException)
- {
- DosBeep( 250, 30);
- DosBeep( 500, 30);
- DosBeep(1000, 30);
- DosBeep(2000, 30);
- DosBeep(4000, 30);
- DosBeep(2000, 30);
- DosBeep(1000, 30);
- DosBeep( 500, 30);
- DosBeep( 250, 30);
- }
-#endif
-
- // generic exception info
- DosQuerySysInfo(QSV_VERSION_MAJOR, // 11
- QSV_VERSION_MINOR, // 12
- &aulBuf, sizeof(aulBuf));
- // Warp 3 is reported as 20.30
- // Warp 4 is reported as 20.40
- // Aurora is reported as 20.45
-
- if (aulBuf[0] == 20)
- {
- switch (aulBuf[1])
- {
- case 30: pcszVersion = "Warp 3"; break;
- case 40: pcszVersion = "Warp 4"; break;
- case 45: pcszVersion = "WSeB kernel"; break;
- }
- }
- fprintf(file,
- "Running OS/2 version: %u.%u (%s)\n",
- aulBuf[0], // major
- aulBuf[1],
- pcszVersion);
-
-
- // generic exception info
- fprintf(file,
- "\n%s:\n Exception type: %08lX\n Address: %08lX\n Params: ",
- pszHandlerName,
- pReportRec->ExceptionNum,
- (ULONG)pReportRec->ExceptionAddress);
- for (ul = 0; ul < pReportRec->cParameters; ul++)
- {
- fprintf(file, "%08lX ",
- pReportRec->ExceptionInfo[ul]);
- }
-
- // now explain the exception in a bit more detail;
- // depending on the exception, pReportRec->ExceptionInfo
- // contains some useful data
- switch (pReportRec->ExceptionNum)
- {
- case XCPT_ACCESS_VIOLATION:
- fprintf(file, "\nXCPT_ACCESS_VIOLATION: ");
- if (pReportRec->ExceptionInfo[0] & XCPT_READ_ACCESS)
- fprintf(file, "Invalid read access from 0x%04lX:%08lX.\n",
- pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]);
- else if (pReportRec->ExceptionInfo[0] & XCPT_WRITE_ACCESS)
- fprintf(file, "Invalid write access to 0x%04lX:%08lX.\n",
- pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]);
- else if (pReportRec->ExceptionInfo[0] & XCPT_SPACE_ACCESS)
- fprintf(file, "Invalid space access at 0x%04lX.\n",
- pReportRec->ExceptionInfo[1]);
- else if (pReportRec->ExceptionInfo[0] & XCPT_LIMIT_ACCESS)
- fprintf(file, "Invalid limit access occurred.\n");
- else if (pReportRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS)
- fprintf(file, "unknown at 0x%04lX:%08lX\n",
- pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]);
- fprintf(file,
- "Explanation: An attempt was made to access a memory object which does\n"
- " not belong to the current process. Most probable causes\n"
- " for this are that an invalid pointer was used, there was\n"
- " confusion with administering memory or error conditions \n"
- " were not properly checked for.\n");
- break;
-
- case XCPT_INTEGER_DIVIDE_BY_ZERO:
- fprintf(file, "\nXCPT_INTEGER_DIVIDE_BY_ZERO.\n");
- fprintf(file,
- "Explanation: An attempt was made to divide an integer value by zero,\n"
- " which is not defined.\n");
- break;
-
- case XCPT_ILLEGAL_INSTRUCTION:
- fprintf(file, "\nXCPT_ILLEGAL_INSTRUCTION.\n");
- fprintf(file,
- "Explanation: An attempt was made to execute an instruction that\n"
- " is not defined on this machine's architecture.\n");
- break;
-
- case XCPT_PRIVILEGED_INSTRUCTION:
- fprintf(file, "\nXCPT_PRIVILEGED_INSTRUCTION.\n");
- fprintf(file,
- "Explanation: An attempt was made to execute an instruction that\n"
- " is not permitted in the current machine mode or that\n"
- " the program had no permission to execute.\n");
- break;
-
- case XCPT_INTEGER_OVERFLOW:
- fprintf(file, "\nXCPT_INTEGER_OVERFLOW.\n");
- fprintf(file,
- "Explanation: An integer operation generated a carry-out of the most\n"
- " significant bit. This is a sign of an attempt to store\n"
- " a value which does not fit into an integer variable.\n");
- break;
-
- default:
- fprintf(file, "\nUnknown OS/2 exception number %d.\n", pReportRec->ExceptionNum);
- fprintf(file, "Look this up in the OS/2 header files.\n");
- break;
- }
-
- // V0.9.16 (2001-11-02) [pr]: We already got this info. above - this overwrites the
- // original values before the priority change, which is rather confusing.
- // if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR)
- {
- /*
- * process info:
- *
- */
-
- if ((ptib) && (ppib)) // (99-11-01) [umoeller]
- {
- if (pContextRec->ContextFlags & CONTEXT_CONTROL)
- {
- // get the main module
- hMod1 = ppib->pib_hmte;
- DosQueryModuleName(hMod1,
- sizeof(szMod1),
- szMod1);
-
- // get the trapping module
- DosQueryModFromEIP(&hMod2,
- &ulObjNum,
- sizeof(szMod2),
- szMod2,
- &ulOffset,
- pContextRec->ctx_RegEip);
- DosQueryModuleName(hMod2,
- sizeof(szMod2),
- szMod2);
- }
-
- fprintf(file,
- "\nProcess information:"
- "\n Process ID: 0x%lX"
- "\n Process module: 0x%lX (%s)"
- "\n Trapping module: 0x%lX (%s)"
- "\n Object: %ld\n", // V0.9.16 (2001-11-02) [pr]: make this display signed
- ppib->pib_ulpid,
- hMod1, szMod1,
- hMod2, szMod2,
- ulObjNum);
-
- fprintf(file,
- "\nTrapping thread information:"
- "\n Thread ID: 0x%lX (%lu)"
- "\n Thread slot ID: 0x%lX (%lu)" // added V0.9.19 (2002-03-28) [umoeller]
- "\n Priority: 0x%lX\n",
- ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ultid,
- ptib->tib_ordinal, ptib->tib_ordinal,
- ulOldPriority);
- }
- else
- fprintf(file, "\nProcess information was not available.");
-
- /*
- * now call the hook, if one has been defined,
- * so that the application can write additional
- * information to the traplog (V0.9.0)
- */
-
- if (G_pfnExcHook)
- G_pfnExcHook(file, ptib, ulOldPriority); // V0.9.16 (2001-12-02) [pr]
-
- // *** registers
-
- fprintf(file, "\nRegisters:");
- if (pContextRec->ContextFlags & CONTEXT_INTEGER)
- {
- // DS the following 4 added V0.9.6 (2000-11-06) [umoeller]
- fprintf(file, "\n DS = %08lX ", pContextRec->ctx_SegDs);
- excDescribePage(file, pContextRec->ctx_SegDs);
- // ES
- fprintf(file, "\n ES = %08lX ", pContextRec->ctx_SegEs);
- excDescribePage(file, pContextRec->ctx_SegEs);
- // FS
- fprintf(file, "\n FS = %08lX ", pContextRec->ctx_SegFs);
- excDescribePage(file, pContextRec->ctx_SegFs);
- // GS
- fprintf(file, "\n GS = %08lX ", pContextRec->ctx_SegGs);
- excDescribePage(file, pContextRec->ctx_SegGs);
-
- // EAX
- fprintf(file, "\n EAX = %08lX ", pContextRec->ctx_RegEax);
- excDescribePage(file, pContextRec->ctx_RegEax);
- // EBX
- fprintf(file, "\n EBX = %08lX ", pContextRec->ctx_RegEbx);
- excDescribePage(file, pContextRec->ctx_RegEbx);
- // ECX
- fprintf(file, "\n ECX = %08lX ", pContextRec->ctx_RegEcx);
- excDescribePage(file, pContextRec->ctx_RegEcx);
- // EDX
- fprintf(file, "\n EDX = %08lX ", pContextRec->ctx_RegEdx);
- excDescribePage(file, pContextRec->ctx_RegEdx);
- // ESI
- fprintf(file, "\n ESI = %08lX ", pContextRec->ctx_RegEsi);
- excDescribePage(file, pContextRec->ctx_RegEsi);
- // EDI
- fprintf(file, "\n EDI = %08lX ", pContextRec->ctx_RegEdi);
- excDescribePage(file, pContextRec->ctx_RegEdi);
- fprintf(file, "\n");
- }
- else
- fprintf(file, " not available\n");
-
- if (pContextRec->ContextFlags & CONTEXT_CONTROL)
- {
-
- // *** instruction
-
- fprintf(file, "Instruction pointer (where exception occurred):\n CS:EIP = %04lX:%08lX ",
- pContextRec->ctx_SegCs,
- pContextRec->ctx_RegEip);
- excDescribePage(file, pContextRec->ctx_RegEip);
-
- // *** CPU flags
-
- fprintf(file, "\n EFLAGS = %08lX", pContextRec->ctx_EFlags);
-
- /*
- * stack:
- *
- */
-
- fprintf(file, "\nStack:\n Base: %08lX\n Limit: %08lX",
- (ULONG)(ptib ? ptib->tib_pstack : 0),
- (ULONG)(ptib ? ptib->tib_pstacklimit : 0));
- fprintf(file, "\n SS:ESP = %04lX:%08lX ",
- pContextRec->ctx_SegSs,
- pContextRec->ctx_RegEsp);
- excDescribePage(file, pContextRec->ctx_RegEsp);
-
- fprintf(file, "\n EBP = %08lX ", pContextRec->ctx_RegEbp);
- excDescribePage(file, pContextRec->ctx_RegEbp);
-
- /*
- * stack dump:
- */
-
- if (ptib != 0)
- {
- excDumpStackFrames(file, ptib, pContextRec);
- }
- }
- }
- fprintf(file, "\n");
-
- // reset old priority
- DosSetPriority(PRTYS_THREAD,
- (ulOldPriority & 0x0F00) >> 8,
- (UCHAR)ulOldPriority,
- 0); // current thread
-
- // lower global flag again V0.9.13 (2001-06-19) [umoeller]
- G_ulExplainExceptionRunning--;
-}
-
-/* ******************************************************************
- *
- * Exported routines
- *
- ********************************************************************/
-
-/*
- *@@ excRegisterHooks:
- * this registers hooks which get called for
- * exception handlers. You can set any of the
- * hooks to NULL for safe defaults (see top of
- * except.c for details). You can set none,
- * one, or both of the hooks, and you can call
- * this function several times.
- *
- * Both hooks get called whenever an exception
- * occurs, so there better be no bugs in these
- * routines. ;-) They only get called from
- * within excHandlerLoud (because excHandlerQuiet
- * writes no trap logs).
- *
- * The hooks are as follows:
- *
- * -- pfnExcOpenFileNew gets called to open
- * the trap log file. This must return a FILE*
- * pointer from fopen(). If this is not defined,
- * ?:\TRAP.LOG is used. Use this to specify a
- * different file and have some notes written
- * into it before the actual exception info.
- *
- * -- pfnExcHookNew gets called while the trap log
- * is being written. At this point,
- * the following info has been written into
- * the trap log already:
- * -- exception type/address block
- * -- exception explanation
- * -- process information
- *
- * _After_ the hook, the exception handler
- * continues with the "Registers" information
- * and stack dump/analysis.
- *
- * Use this hook to write additional application
- * info into the trap log, such as the state
- * of your own threads and mutexes.
- *
- * -- pfnExcHookError gets called when the TRY_* macros
- * fail to install an exception handler (when
- * DosSetExceptionHandler fails). I've never seen
- * this happen.
- *
- *@@added V0.9.0 [umoeller]
- *@@changed V0.9.2 (2000-03-10) [umoeller]: pfnExcHookError added
- */
-
-VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew,
- PFNEXCHOOK pfnExcHookNew,
- PFNEXCHOOKERROR pfnExcHookError,
- BOOL fBeepOnExceptionNew)
-{
- // adjust the global variables
- G_pfnExcOpenFile = pfnExcOpenFileNew;
- G_pfnExcHook = pfnExcHookNew;
- G_pfnExcHookError = pfnExcHookError;
- G_fBeepOnException = fBeepOnExceptionNew;
-}
-
-/*
- *@@ excHandlerLoud:
- * this is the "sophisticated" exception handler;
- * which gives forth a loud sequence of beeps thru the
- * speaker, writes a trap log and then returns back
- * to the thread to continue execution, i.e. the
- * default OS/2 exception handler will never get
- * called.
- *
- * This requires a setjmp() call on
- * EXCEPTIONREGISTRATIONRECORD2.jmpThread before
- * being installed. The TRY_LOUD macro will take
- * care of this for you (see except.c).
- *
- * This intercepts the following exceptions (see
- * the OS/2 Control Program Reference for details):
- *
- * -- XCPT_ACCESS_VIOLATION (traps 0x0d, 0x0e)
- * -- XCPT_INTEGER_DIVIDE_BY_ZERO (trap 0)
- * -- XCPT_ILLEGAL_INSTRUCTION (trap 6)
- * -- XCPT_PRIVILEGED_INSTRUCTION
- * -- XCPT_INTEGER_OVERFLOW (trap 4)
- *
- * For these exceptions, we call the functions in debug.c
- * to try to find debug code or SYM file information about
- * what source code corresponds to the error.
- *
- * See excRegisterHooks for the default setup of this.
- *
- * Note that to get meaningful debugging information
- * in this handler's traplog, you need the following:
- *
- * a) have a MAP file created at link time (/MAP)
- *
- * b) convert the MAP to a SYM file using MAPSYM
- *
- * c) put the SYM file in the same directory of
- * the module (EXE or DLL). This must have the
- * same filestem as the module.
- *
- * All other exceptions are passed to the next handler
- * in the exception handler chain. This might be the
- * C/C++ compiler handler or the default OS/2 handler,
- * which will probably terminate the process.
- *
- *@@changed V0.9.0 [umoeller]: added support for thread termination
- *@@changed V0.9.2 (2000-03-10) [umoeller]: switched date format to ISO
- *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that
- */
-
-ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec,
- PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
- PCONTEXTRECORD pContextRec,
- PVOID pv)
-{
- /* From the VAC++3 docs:
- * "The first thing an exception handler should do is check the
- * exception flags. If EH_EXIT_UNWIND is set, meaning
- * the thread is ending, the handler tells the operating system
- * to pass the exception to the next exception handler. It does the
- * same if the EH_UNWINDING flag is set, the flag that indicates
- * this exception handler is being removed.
- * The EH_NESTED_CALL flag indicates whether the exception
- * occurred within an exception handler. If the handler does
- * not check this flag, recursive exceptions could occur until
- * there is no stack remaining."
- * So for all these conditions, we exit immediately.
- */
-
- if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND)
- return (XCPT_CONTINUE_SEARCH);
- if (pReportRec->fHandlerFlags & EH_UNWINDING)
- return (XCPT_CONTINUE_SEARCH);
- if (pReportRec->fHandlerFlags & EH_NESTED_CALL)
- return (XCPT_CONTINUE_SEARCH);
-
- switch (pReportRec->ExceptionNum)
- {
- case XCPT_ACCESS_VIOLATION:
- case XCPT_INTEGER_DIVIDE_BY_ZERO:
- case XCPT_ILLEGAL_INSTRUCTION:
- case XCPT_PRIVILEGED_INSTRUCTION:
- case XCPT_INVALID_LOCK_SEQUENCE:
- case XCPT_INTEGER_OVERFLOW:
- {
- // "real" exceptions:
- FILE *file;
-
- // open traplog file;
- if (G_pfnExcOpenFile)
- // hook defined for this: call it
- file = (*G_pfnExcOpenFile)();
- else
- {
- CHAR szFileName[100];
- // no hook defined: open some
- // default traplog file in root directory of
- // boot drive
- sprintf(szFileName, "%c:\\trap.log", doshQueryBootDrive());
- file = fopen(szFileName, "a");
-
- if (file)
- {
- DATETIME DT;
- DosGetDateTime(&DT);
- fprintf(file,
- "\nTrap message -- Date: %04d-%02d-%02d, Time: %02d:%02d:%02d\n",
- DT.year, DT.month, DT.day,
- DT.hours, DT.minutes, DT.seconds);
- fprintf(file, "------------------------------------------------\n");
-
- }
- }
-
- // write error log
- excExplainException(file,
- "excHandlerLoud",
- pReportRec,
- pContextRec);
- fclose(file);
-
- // copy report rec to user buffer
- // V0.9.19 (2002-05-07) [umoeller]
- memcpy(&pRegRec2->err,
- pReportRec,
- sizeof(EXCEPTIONREPORTRECORD));
-
- // jump back to failing routine
- longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum);
- break; }
- }
-
- // not handled
- return (XCPT_CONTINUE_SEARCH);
-}
-
-/*
- *@@ excHandlerQuiet:
- * "quiet" xcpt handler, which simply suppresses exceptions;
- * this is useful for certain error-prone functions, where
- * exceptions are likely to appear, for example used by
- * wpshCheckObject to implement a fail-safe SOM object check.
- *
- * This does _not_ write an error log and makes _no_ sound.
- * This simply jumps back to the trapping thread or
- * calls EXCEPTIONREGISTRATIONRECORD2.pfnOnKill.
- *
- * Other than that, this behaves like excHandlerLoud.
- *
- * This is best registered thru the TRY_QUIET macro
- * (new with V0.84, described in except.c), which
- * does the necessary setup.
- *
- *@@changed V0.9.0 [umoeller]: added support for thread termination
- *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that
- */
-
-ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec,
- PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
- PCONTEXTRECORD pContextRec,
- PVOID pv)
-{
- if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND)
- return (XCPT_CONTINUE_SEARCH);
- if (pReportRec->fHandlerFlags & EH_UNWINDING)
- return (XCPT_CONTINUE_SEARCH);
- if (pReportRec->fHandlerFlags & EH_NESTED_CALL)
- return (XCPT_CONTINUE_SEARCH);
-
- switch (pReportRec->ExceptionNum)
- {
- case XCPT_ACCESS_VIOLATION:
- case XCPT_INTEGER_DIVIDE_BY_ZERO:
- case XCPT_ILLEGAL_INSTRUCTION:
- case XCPT_PRIVILEGED_INSTRUCTION:
- case XCPT_INVALID_LOCK_SEQUENCE:
- case XCPT_INTEGER_OVERFLOW:
- // write excpt explanation only if the
- // resp. debugging #define is set (setup.h)
- #ifdef DEBUG_WRITEQUIETEXCPT
- {
- FILE *file = excOpenTraplogFile();
- excExplainException(file,
- "excHandlerQuiet",
- pReportRec,
- pContextRec);
- fclose(file);
- }
- #endif
-
- // copy report rec to user buffer
- // V0.9.19 (2002-05-07) [umoeller]
- memcpy(&pRegRec2->err,
- pReportRec,
- sizeof(EXCEPTIONREPORTRECORD));
-
- // jump back to failing routine
- longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum);
- break;
-
- default:
- break;
- }
-
- return (XCPT_CONTINUE_SEARCH);
-}
-
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */