Changeset 151 for trunk


Ignore:
Timestamp:
Nov 9, 2006, 11:42:05 PM (19 years ago)
Author:
dmik
Message:

Common: System Exceptions:

  • The trap report file subdirectory is changed from '.systraps' to 'SysTraps' for better FAT16 compatibility.
  • Added handling of the XCPT_BREAKPOINT exception; useful for debug assertions followed by a breakpoint trap (i.e. the 'int 3' CPU instruction) in order to get the call stack when such an assertion is hit.
  • Added some doxygen documentation for QtOS2SysXcptMainHandler and friends.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/tools/qsysxcpt_pm.cpp

    r150 r151  
    6161/** @class QtOS2SysXcptMainHandler qt_os2.h
    6262 *
    63  *  @todo (r=dmik) describe...
     63 *  The QtOS2SysXcptMainHandler class is used to install the OS2/ system
     64 *  exception handler on the main thread of the Qt application.
    6465 *
    65  *  - must be instantiated on the stack of the main thread only
    66  *  - should be instantiated before a QAplication instance is created
    67  *    (does nothing otherwise)
    68  *  - note that callback can be called on any thread
     66 *  The installed exception handler will catch most fatal exceptions (commonly
     67 *  referred to as traps), such as memory access violation, and create a
     68 *  detailed report about the state of the failed application (process name,
     69 *  loaded modules, thread states and call stacks). The created report is saved
     70 *  in the user home directory and is supposed to be sent to the application
     71 *  developer (which makes it much easier to find a reason of the trap and
     72 *  therefore gives a better chance that the problem will be fixed).
     73 *
     74 *  In order to install the exception handler, an instance of this class is
     75 *  created on the stack of the main thread. The best place for it is the
     76 *  first line of the application's main() function, before doing anything else.
     77 *  One doesn't need (and <b>should not</b>) create a QApplication instance
     78 *  before installing the exception handler. If you do so, then QApplication
     79 *  will install the same exception handler on its own, which is not a preferred
     80 *  way for two reasons:
     81 *  <ul>
     82 *  <li>QApplication uses a hack to attach the exception handler to the
     83 *      exception handler installed by the compiler's C Library (LIBC). This
     84 *      hack will not work if there is no exception handler provided by LIBC
     85 *      or it may work incorrectly if there are other exception handlers
     86 *      installed after it using the same (or similar hack).
     87 *  <li>There is no way to specify the exception handler callback (see below).
     88 *  </ul>
     89 *
     90 *  There may be only one instance of this class and it must be created only on
     91 *  the main (UI) thread. All other threads started by Qt using the QThread
     92 *  class will have the exception handler installed authomatically before the
     93 *  QThread::run() method starts execution, so there is no need to install it
     94 *  explicitly.
     95 *
     96 *  Note that QtOS2SysXcptMainHandler is a stack-based class, which means that
     97 *  you cannot create an instance using the new operator (you will get a
     98 *  compile time error). You might want to create it as a static variable (for
     99 *  example, if you want to catch exceptions happening before main() is entered,
     100 *  such as initialization of other static variables), however this is not
     101 *  currently supported and may work incorrectly because the OS/2 system
     102 *  documentation clearly states that the exception handler data must be
     103 *  allocated on the stack. Here is a typical usage pattern for installing the
     104 *  exception handler:
     105 *
     106 *  \code
     107 *  int main (int argc, char **argv)
     108 *  {
     109 *      QtOS2SysXcptMainHandler sysXcptHandler( psiOS2SysXcptCallback );
     110 *
     111 *      QApplication app;
     112 *      MyWidget wgt;
     113 *      app.setMainWidget (&wgt);
     114 *      wgt.show();
     115 *      return app.exec();
     116 *  }
     117 *  \endcode
     118 *
     119 *  The exception report is an XML file with the well-defined structure and
     120 *  contains enough information to find symbols corresponding to execution
     121 *  points on the call stack (provided that there is a .SYM file for a program
     122 *  or a library module). This file is always created in the SysTraps
     123 *  subdirectory of the user's home directory (or of the root directory of the
     124 *  boot drive if no home directory exists). Currently there is no way to
     125 *  specify a different location. A separate report file is created per every
     126 *  trap.
     127 *
     128 *  In order to store application-specific information in the report file,
     129 *  an application can install the exception handler callback that is
     130 *  called at certain points during exception handling. This callback is
     131 *  specified as an argument to the QtOS2SysXcptMainHandler constructor, but
     132 *  it will be called on any Qt thread that caught an exception, not
     133 *  necessarily the main one.
     134 *
     135 *  The callback function has the following prototype:
     136 *  \code
     137 *  int XcptCallback( QtOS2SysXcptReq req, QtOS2SysXcptWriter writer, int reserved );
     138 *  \endcode
     139 *  \a req is one of the QtOS2SysXcptReq values describing what type of
     140 *  information the exception handler wants to get from the callback, \a writer
     141 *  is the function used by the callback to write the requested information to
     142 *  the report file and \a reserved is a reserved value which is currently
     143 *  always zero.
     144 *
     145 *  The callback can be called by the exception handler in two modes: \em ask
     146 *  mode or \em let mode. In the "ask" mode (indicated by the NULL \a writer
     147 *  argument), the handler asks whether the callback supports the requested
     148 *  bit of information, as defined by the \a req argument. In the "let" mode
     149 *  (where \a writer is not NULL), it lets the callback to write the requested
     150 *  information to the report file using the supplied \a writer. Note that the
     151 *  callback should not deal with any structural report details (such as XML
     152 *  tags or character escaping) -- the string it writes is just an arbitrary
     153 *  character value for the requested attribute. The meaning of different
     154 *  QtOS2SysXcptReq values can be easily explained with an example:
     155 *
     156 *  \code
     157    QString PROG_NAME = "MyApp";
     158    QString PROG_VERSION = "0.1";
     159 
     160    int psiOS2SysXcptCallback( QtOS2SysXcptReq req, QtOS2SysXcptWriter writer, int )
     161    {
     162        switch( req )
     163        {
     164            // application name
     165            case QtOS2SysXcptReq_AppName:
     166                if ( writer ) writer( PROG_NAME.latin1() );
     167                return TRUE;
     168
     169            // application version
     170            case QtOS2SysXcptReq_AppVer:
     171                if ( writer ) writer( PROG_VERSION.latin1() );
     172                return TRUE;
     173
     174            // e-mail to send generated trap reports to
     175            // (can be used by trap report handling utilities to assist the
     176            // user to compose and send trap reports to the developer)
     177            case QtOS2SysXcptReq_ReportTo:
     178                if ( writer ) writer( "my-traps@some.where" );
     179                return TRUE;
     180
     181            // recommended subject of the generated e-mail message 
     182            // (same purpose as above)
     183            case QtOS2SysXcptReq_ReportSubj:
     184                // we don't need to provide this kind of information,
     185                // so simply return FALSE
     186                return TRUE;
     187
     188            default:
     189                break;
     190        }
     191
     192        // we don't support any other information requests
     193        return FALSE;
     194    }
     195 *  \endcode
    69196 */
    70197
     
    75202
    76203/**
    77  *  @todo (r=dmik) describe...       
     204 *  Installs the exception handler on the main thread and registers \a cb
     205 *  as the exception handler callback. If \a cb is NULL (by default), then no
     206 *  user-supplied exception callback will be registered.
    78207 */
    79208QtOS2SysXcptMainHandler::QtOS2SysXcptMainHandler (QtOS2SysXcptCallback cb)
     
    108237
    109238/**
    110  *  @todo (r=dmik) describe...       
     239 *  Uninstalls the exception handler installed by the constructor.       
    111240 */
    112241QtOS2SysXcptMainHandler::~QtOS2SysXcptMainHandler()
     
    9421071
    9431072    char szFileName[CCHMAXPATH];
    944     char szDir[] = "\\.systrap";
     1073    char szDir[] = "\\SysTraps";
    9451074    char szFile[] = "\\12345678.123";
    9461075    enum { cbFileName = sizeof(szFileName) };
     
    10821211        case XCPT_INVALID_LOCK_SEQUENCE:
    10831212        case XCPT_INTEGER_OVERFLOW:
     1213        case XCPT_BREAKPOINT:
    10841214        {
    10851215            /* "real" exceptions: */
Note: See TracChangeset for help on using the changeset viewer.