Changeset 139 for trunk/src/tools


Ignore:
Timestamp:
Oct 20, 2006, 11:44:52 PM (19 years ago)
Author:
dmik
Message:

Kernel/Tools: Improved OS/2 exception handling:

  • Moved the excpetion handler code from the kernel module to the tools module (defines are now in qt_os2.h instead of qwindowdefs_pm.h);
  • QT_PM_NO_SYSEXCEPTIONS is renamed to QT_OS2_NO_SYSEXCEPTIONS;
  • Added the QtOS2SysXcptMainHandler stack-based class to correctly install the exception handler on the main thread, as well as provide an optional callback.
Location:
trunk/src/tools
Files:
1 edited
1 moved

Legend:

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

    r138 r139  
    4141 */
    4242
    43 #if !defined(QT_PM_NO_SYSEXCEPTIONS)   
     43#if !defined(QT_OS2_NO_SYSEXCEPTIONS)
    4444 
    4545#include "qt_os2.h"
     
    5959//     contexts to the trap file when a real exception happens on one thread
    6060
    61 extern ERR qt_libcExceptionHandler; // defined in qapplication_pm.cpp
    62 
    63 static QtSysXcptCallback qt_excCallback = NULL;
    64 static FILE *qt_excWriteMsg_file = NULL;
    65 
    66 static void qt_excCallbackWriter( const char *pcszMsg );
    67 
    68 /**
    69  *  Installs \a cb as the OS/2 system exception handler callback.
    70  *  Passing NULL as \a cb will uninstall the currently installed callback.
    71  *
    72  *  @todo (r=dmik) describe the callback... 
    73  */
    74 Q_EXPORT QtSysXcptCallback qInstallSysXcptCallback( QtSysXcptCallback cb )
    75 {
    76     QtSysXcptCallback tmp = qt_excCallback;
    77     qt_excCallback = cb;
    78     return tmp;
     61/*! \class QtOS2SysXcptMainHandler qt_os2.h
     62
     63    @todo (r=dmik) describe...
     64   
     65    - must be instantiated on the stack of the main thread only
     66    - must be instantiated before a QAplication instance is created
     67*/
     68
     69/* static */
     70bool QtOS2SysXcptMainHandler::installed = FALSE;
     71QtOS2SysXcptCallback QtOS2SysXcptMainHandler::callback = NULL;
     72ERR QtOS2SysXcptMainHandler::libcHandler = NULL;
     73
     74/*!
     75    @todo (r=dmik) describe...       
     76*/
     77QtOS2SysXcptMainHandler::QtOS2SysXcptMainHandler( QtOS2SysXcptCallback cb )
     78{
     79    rec.prev_structure = NULL;
     80    rec.ExceptionHandler = NULL;
     81   
     82    PTIB ptib = NULL;
     83    DosGetInfoBlocks( &ptib, NULL );
     84    Q_ASSERT( ptib && ptib->tib_ptib2 );
     85
     86    if ( ptib && ptib->tib_ptib2 )
     87    {
     88        // must be instantiated only on the main (first) thread
     89        Q_ASSERT( ptib->tib_ptib2->tib2_ultid == 1 );
     90        if ( ptib->tib_ptib2->tib2_ultid == 1 )
     91        {
     92            // must not be already instantiated
     93            Q_ASSERT( installed == FALSE );
     94            Q_ASSERT( libcHandler == NULL );
     95            if ( installed == FALSE && libcHandler == NULL )
     96            {
     97                installed = TRUE;
     98                callback = cb;
     99                // install the exception handler for the main thread
     100                rec.ExceptionHandler = handler;
     101                DosSetExceptionHandler( &rec );
     102            }
     103        }
     104    }
     105}
     106
     107/*!
     108    @todo (r=dmik) describe...       
     109*/
     110QtOS2SysXcptMainHandler::~QtOS2SysXcptMainHandler()
     111{
     112    Q_ASSERT( rec.ExceptionHandler == handler || rec.ExceptionHandler == NULL );
     113    if ( rec.ExceptionHandler == handler )
     114    {
     115        // uninstall the exception handler for the main thread
     116        DosUnsetExceptionHandler( &rec );
     117        rec.ExceptionHandler = NULL;
     118        callback = NULL;
     119        installed = FALSE;
     120    }
    79121}
    80122
    81123static void qt_excEscapeString( FILE *file, const char *pcszStr );
    82124
    83 static void qt_excCallbackWriter( const char *msg )
    84 {
    85     if ( qt_excWriteMsg_file )
    86         qt_excEscapeString( qt_excWriteMsg_file, msg );
    87 }
    88 
    89 inline int qt_excAskCallback( QtSysXcptReq req )
    90 {
    91     if ( qt_excCallback )
    92         return qt_excCallback( req, NULL, 0 );
    93     return FALSE;
    94 }
    95 
    96 inline int qt_excLetCallback( QtSysXcptReq req )
    97 {
    98     if ( qt_excCallback )
    99         return qt_excCallback( req, qt_excCallbackWriter, 0 );
    100     return FALSE;
    101 }
    102 
    103 /**
    104  *  Writes the given string with [<>&'"] characters escaped for XML.
    105  */
     125#define XcptPvt QtOS2SysXcptMainHandler::Private
     126
     127class XcptPvt
     128{
     129public:
     130    static void callbackWriter( const char *msg );
     131
     132    static inline int askCallback( QtOS2SysXcptReq req )
     133    {
     134        if ( callback )
     135            return callback( req, NULL, 0 );
     136        return FALSE;
     137    }
     138
     139    static inline int letCallback( QtOS2SysXcptReq req )
     140    {
     141        if ( callback )
     142            return callback( req, callbackWriter, 0 );
     143        return FALSE;
     144    }
     145   
     146    static FILE *file;
     147};
     148
     149/* static */
     150FILE *XcptPvt::file = NULL;
     151
     152/* static */
     153void XcptPvt::callbackWriter( const char *msg )
     154{
     155    if ( file )
     156        qt_excEscapeString( file, msg );
     157}
     158
     159/*! \internal
     160    Writes the given string with [<>&'"] characters escaped for XML.
     161*/
    106162static void qt_excEscapeString( FILE *file, const char *pcszStr )
    107163{
     
    130186}
    131187
    132 /**
    133  *  Writes the given error message.
    134  */
     188/*! \internal
     189    Writes the given error message.
     190*/
    135191static void qt_excWriteErrorMsg( FILE *file, ULONG ulIndent, const char *pcszMsg,
    136192                                 ... )
     
    147203}
    148204
    149 /**
    150  *  Writes the register name, value and optionally memory flags
    151  */
     205/*! \internal
     206    Writes the register name, value and optionally memory flags
     207*/
    152208static void qt_excWriteReg( FILE *file, const char *pszName, ULONG ulValue,
    153209                            BOOL bQueryMem = TRUE )
    154210{
    155     fprintf( file, "    <Register name=\"%s\" value=\"%08lX\"",
     211    fprintf( file, "     <Register name=\"%s\" value=\"%08lX\"",
    156212             pszName, ulValue );
    157213
     
    175231}
    176232
    177 /**
    178  *  Writes information about a signle stack frame.
    179  */
     233/*! \internal
     234    Writes information about a signle stack frame.
     235*/
    180236static void qt_excWriteStackFrame( FILE *file, ULONG ulPointer, ULONG ulAddress )
    181237{
     
    187243
    188244    if ( ulPointer )
    189         fprintf( file, "    <Frame pointer=\"%08lX\">\n", ulPointer );
     245        fprintf( file, "     <Frame pointer=\"%08lX\">\n", ulPointer );
    190246    else
    191         fprintf( file, "    <Frame pointer=\"current\">\n" );
     247        fprintf( file, "     <Frame pointer=\"current\">\n" );
    192248           
    193249    if ( ulAddress )
    194250    {
    195         fprintf( file, "     <Location address=\"%08lX\">\n", ulAddress );
     251        fprintf( file, "      <Location address=\"%08lX\">\n", ulAddress );
    196252   
    197253        arc = DosQueryModFromEIP( &hMod, &ulObject,
     
    205261        {
    206262            DosQueryModuleName( hMod, sizeof(szMod), szMod );
    207             fprintf( file, "      <Module ID=\"%04lX\" name=\"", hMod );
     263            fprintf( file, "       <Module ID=\"%04lX\" name=\"", hMod );
    208264            qt_excEscapeString( file, szMod );
    209265            fprintf( file, "\" \n"
    210                            "              segment=\"%04lX\" offset=\"%08lX\"/>\n",
     266                           "               segment=\"%04lX\" offset=\"%08lX\"/>\n",
    211267                     ulObject + 1, ulOffset );
    212268/// @todo (r=dmik) use .DBG and .SYM files to get symbols
     
    221277        qt_excWriteErrorMsg( file, 5, "Unable to access stack frame" );
    222278   
    223     fprintf( file, "     </Location>\n"
    224                    "    </Frame>\n" );
    225 }
    226 
    227 /**
    228  *  Walks the stack and writes information about stack frames.
    229  */
     279    fprintf( file, "      </Location>\n"
     280                   "     </Frame>\n" );
     281}
     282
     283/*! \internal
     284    Walks the stack and writes information about stack frames.
     285*/
    230286static void qt_excWriteStackFrames( FILE *file, PTIB ptib,
    231287                                    PCONTEXTRECORD pContextRec )
     
    233289    PULONG pulStackWord = 0;
    234290
    235     fprintf( file, "   <Frames>\n" );
     291    fprintf( file, "    <Frames>\n" );
    236292
    237293    // first the trapping address itself
     
    255311                         != (PAG_COMMIT|PAG_READ)) )
    256312            {
    257                 fprintf( file, "    <Frame pointer=\"%08lX\">\n",
     313                fprintf( file, "     <Frame pointer=\"%08lX\">\n",
    258314                         (ULONG) pulStackWord );
    259                 qt_excWriteErrorMsg( file, 5,
     315                qt_excWriteErrorMsg( file, 6,
    260316                                     "Unable to access stack frame, DosQueryMem "
    261317                                     "returned %lu and flags %08lX",
    262318                                     arc, ulFlagsPage );
    263                 fprintf( file, "    </Frame>\n" );
     319                fprintf( file, "     </Frame>\n" );
    264320                pulStackWord += 0x1000;
    265321                continue; // while
     
    271327    } // end while
    272328
    273     fprintf( file, "   </Frames>\n" );
    274 }
    275 
    276 /**
    277  *  Writes the thread information.
    278  */
     329    fprintf( file, "    </Frames>\n" );
     330}
     331
     332/*! \internal
     333    Writes the thread information.
     334*/
    279335static void qt_excWriteThreadInfo( FILE *file, PTIB ptib,
    280336                                   PEXCEPTIONREPORTRECORD pReportRec,
     
    289345    DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0 );
    290346
    291     fprintf( file, " <Thread ID=\"%04lX\" slot=\"%04lX\" "
    292                             "priority=\"%04lX\" "
    293                             "mc=\"%04lX\" mcf=\"%04lX\">\n",
     347    fprintf( file, "  <Thread ID=\"%04lX\" slot=\"%04lX\" "
     348                             "priority=\"%04lX\" "
     349                             "mc=\"%04lX\" mcf=\"%04lX\">\n",
    294350             ptib->tib_ptib2->tib2_ultid, ptib->tib_ordinal, ulOldPriority,
    295351             ptib->tib_ptib2->tib2_usMCCount, ptib->tib_ptib2->tib2_fMCForceFlag );
     
    298354
    299355    fprintf( file,
    300              "  <Exception type=\"%08lX\" flags=\"%08lX\" address=\"%08lX\">\n",
     356             "   <Exception type=\"%08lX\" flags=\"%08lX\" address=\"%08lX\">\n",
    301357             pReportRec->ExceptionNum, pReportRec->fHandlerFlags,
    302358             (ULONG) pReportRec->ExceptionAddress );
     
    304360    for ( ul = 0; ul < pReportRec->cParameters;  ++ul )
    305361    {
    306         fprintf( file, "   <Param value=\"%08lX\"/>\n",
     362        fprintf( file, "    <Param value=\"%08lX\"/>\n",
    307363                 pReportRec->ExceptionInfo[ul] );
    308364    }
    309365
    310     fprintf( file, "  </Exception>\n" );
     366    fprintf( file, "   </Exception>\n" );
    311367   
    312368    // *** registers
    313369
    314     fprintf( file, "  <CPU>\n"
    315                    "   <Registers>\n" );
     370    fprintf( file, "   <CPU>\n"
     371                   "    <Registers>\n" );
    316372
    317373    if ( pContextRec->ContextFlags & CONTEXT_SEGMENTS )
     
    343399    }
    344400   
    345     fprintf( file, "   </Registers>\n"
    346                    "  </CPU>\n" );
     401    fprintf( file, "    </Registers>\n"
     402                   "   </CPU>\n" );
    347403
    348404    // *** stack
    349405
    350     fprintf( file, "  <Stack base=\"%08lX\" limit=\"%08lX\">\n",
     406    fprintf( file, "   <Stack base=\"%08lX\" limit=\"%08lX\">\n",
    351407             (ULONG) ptib->tib_pstack,
    352408             (ULONG) ptib->tib_pstacklimit );
     
    357413    }   
    358414   
    359     fprintf( file, "  </Stack>\n"
    360                    " </Thread>\n" );
     415    fprintf( file, "   </Stack>\n"
     416                   "  </Thread>\n" );
    361417   
    362418    // reset old priority
     
    366422}
    367423
    368 /**
    369  * Writes exception information to the log file.
    370  */
     424/*! \internal
     425   Writes exception information to the log file.
     426*/
    371427static void qt_excWriteException( FILE *file,
    372428                                  const char *pszExeName,
     
    382438    {
    383439        fprintf( file, " <Application name=\"" );
    384         if ( qt_excAskCallback( QtSysXcptReq_AppName ) == TRUE )
    385             qt_excLetCallback( QtSysXcptReq_AppName );
     440        if ( XcptPvt::askCallback( QtOS2SysXcptReq_AppName ) == TRUE )
     441            XcptPvt::letCallback( QtOS2SysXcptReq_AppName );
    386442        else
    387443            qt_excEscapeString( file, pszExeBase );
    388444        fprintf( file, "\" version=\"" );
    389         if ( qt_excAskCallback( QtSysXcptReq_AppVer ) == TRUE )
    390             qt_excLetCallback( QtSysXcptReq_AppVer );
     445        if ( XcptPvt::askCallback( QtOS2SysXcptReq_AppVer ) == TRUE )
     446            XcptPvt::letCallback( QtOS2SysXcptReq_AppVer );
    391447        else
    392448            fprintf( file, "unknown" );
    393449        fprintf( file, "\">\n" );
    394450
    395         if ( qt_excAskCallback( QtSysXcptReq_ReportTo ) == TRUE )
     451        if ( XcptPvt::askCallback( QtOS2SysXcptReq_ReportTo ) == TRUE )
    396452        {
    397453            fprintf( file, "  <Report to=\"" );
    398             qt_excLetCallback( QtSysXcptReq_ReportTo );
    399             if ( qt_excAskCallback( QtSysXcptReq_ReportSubj ) == TRUE )
     454            XcptPvt::letCallback( QtOS2SysXcptReq_ReportTo );
     455            if ( XcptPvt::askCallback( QtOS2SysXcptReq_ReportSubj ) == TRUE )
    400456            {
    401457                fprintf( file, "\" subject=\"" );
    402                 qt_excLetCallback( QtSysXcptReq_ReportSubj );
     458                XcptPvt::letCallback( QtOS2SysXcptReq_ReportSubj );
    403459            }
    404460            fprintf( file, "\"/>\n" );
     
    436492        qt_excWriteErrorMsg( file, 1, "ppib is NULL" );
    437493
     494        fprintf( file, " <Threads>\n" );
     495       
    438496    if ( ptib && ptib->tib_ptib2 )
    439497        qt_excWriteThreadInfo( file, ptib, pReportRec, pContextRec );
     
    442500    else
    443501        qt_excWriteErrorMsg( file, 1, "ptib->tib_ptib2 is NULL" );
     502
     503        fprintf( file, " </Threads>\n" );
    444504}
    445505
     
    544604}
    545605
    546 /**
    547  * Qt Exception handler.
    548  */
    549 ULONG APIENTRY qt_exceptionHandler( PEXCEPTIONREPORTRECORD pReportRec,
    550                                     PEXCEPTIONREGISTRATIONRECORD pRegRec,
    551                                     PCONTEXTRECORD pContextRec,
    552                                     PVOID pv )
    553 {
     606/*! \internal
     607    Qt Exception handler.
     608*/
     609/* static */
     610ULONG APIENTRY
     611QtOS2SysXcptMainHandler::handler( PEXCEPTIONREPORTRECORD pReportRec,
     612                                  PEXCEPTIONREGISTRATIONRECORD pRegRec,
     613                                  PCONTEXTRECORD pContextRec,
     614                                  PVOID pv )
     615{
     616    PTIB ptib = NULL;
     617    PPIB ppib = NULL;
     618   
    554619    /* From the VAC++3 docs:
    555620     *      "The first thing an exception handler should do is check the
     
    571636        return XCPT_CONTINUE_SEARCH;
    572637
     638    // can it ever fail?...
     639    DosGetInfoBlocks( &ptib, &ppib );
     640       
    573641    switch (pReportRec->ExceptionNum)
    574642    {
     
    585653            char szFileName[CCHMAXPATH];
    586654            FILE *file = NULL;
    587             PTIB ptib = NULL;
    588             PPIB ppib = NULL;
    589655            char szExeName[CCHMAXPATH] = "unknown";
    590656            char szExeBase[CCHMAXPATH];
    591657           
    592658            DosBeep( 880, 200 );
    593 
    594             // can it ever fail?...
    595             DosGetInfoBlocks( &ptib, &ppib );
    596659
    597660            if ( ppib )
     
    675738                         QT_VERSION_STR );
    676739
    677                 qt_excWriteMsg_file = file;
     740                XcptPvt::file = file;
    678741               
    679742                // write trap information
     
    681744                                      ppib, ptib, pReportRec, pContextRec );
    682745
    683                 qt_excWriteMsg_file = NULL;
     746                XcptPvt::file = NULL;
    684747               
    685748                fprintf( file, "</Trap>\n\n" );
     
    705768    }
    706769
    707     // we never handle the exception ourselves but let the LIBC exception
    708     // handler process it
    709     return qt_libcExceptionHandler( pReportRec, pRegRec, pContextRec, pv );
     770    // we never handle the exception ourselves
     771
     772    if ( ptib && ptib->tib_ptib2 && ptib->tib_ptib2->tib2_ultid == 1 &&
     773         QtOS2SysXcptMainHandler::libcHandler != NULL )
     774    {
     775        // we are on the main thread and were installed from qt_init() during
     776        // QApplication initialization using a hack; pass control back to the
     777        // LIBC exception handler
     778        return QtOS2SysXcptMainHandler::libcHandler( pReportRec, pRegRec,
     779                                                     pContextRec, pv );
     780    }
     781   
     782    return XCPT_CONTINUE_SEARCH;
    710783}
    711784
  • trunk/src/tools/qt_tools.pri

    r8 r139  
    9999                  $$TOOLS_CPP/qwaitcondition_pm.cpp \
    100100                  $$TOOLS_CPP/qthreadstorage_pm.cpp \
    101                   $$TOOLS_CPP/qcriticalsection_p.cpp
     101                  $$TOOLS_CPP/qcriticalsection_p.cpp \
     102                  $$TOOLS_CPP/qsysxcpt_pm.cpp
    102103
    103104        offmac:SOURCES += $$TOOLS_CPP/qdir_mac.cpp \
Note: See TracChangeset for help on using the changeset viewer.