Changeset 156


Ignore:
Timestamp:
Nov 15, 2006, 2:45:23 AM (19 years ago)
Author:
dmik
Message:

Tools: Several fixes to QLibrary:

  • Internal library wrapper could be deleted while still being referenced by the internal library map, producing a segfault on subsequent attempts to load the same library.
  • Internal dynamically allocated library map instance could not be deleted upon application termination if not all QLibrary instances were unloaded.
  • Destroying a QLibrary instance w/o unloading the library would result into a stuck internal library wrapper that would never be deleted.
  • In the debug build, DOS result code was not passed to qSystemWarning() on library resolbe/unload errors causing the PM error code to be printed instead.
Location:
trunk/src/tools
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/tools/qlibrary_p.h

    r8 r156  
    6363public:
    6464    QLibraryPrivate( QLibrary *lib );
     65#if defined(Q_OS_OS2)
     66    ~QLibraryPrivate() { derefLib( FALSE ); }
     67#endif
    6568
    6669#if defined(Q_WS_WIN)
     
    7780
    7881private:
     82#if defined(Q_OS_OS2)
     83    bool derefLib( bool doFree );
     84#endif
     85
    7986    QLibrary *library;
    8087};
  • trunk/src/tools/qlibrary_pm.cpp

    r8 r156  
    4545#ifndef QT_H
    4646#include "qfile.h"
     47#include "qdir.h"
    4748#endif // QT_H
    4849
     
    5556};
    5657
    57 static QMap<QString, LibInstance*> *map = 0;
     58typedef QMap<QCString, LibInstance*> LibInstanceMap;
     59
     60static LibInstanceMap map;
    5861/*
    5962  The platform dependent implementations of
     
    7073{
    7174    if ( pHnd )
    72         return TRUE;
     75        return TRUE;
    7376
    7477#ifdef QT_THREAD_SUPPORT
    7578    // protect map creation/access
    7679    QMutexLocker locker( qt_global_mutexpool ?
    77                         qt_global_mutexpool->get( &map ) : 0 );
     80                        qt_global_mutexpool->get( &map ) : 0 );
    7881#endif // QT_THREAD_SUPPORT
    7982
    80     if ( !map )
    81         map = new QMap<QString, LibInstance*>;
    82 
    83     QString filename = library->library();
    84     if ( map->find(filename) != map->end() ) {
    85         LibInstance *lib = (*map)[filename];
    86         lib->refCount++;
    87         pHnd = lib->module;
    88     }
    89     else {
    90         APIRET rc = 0;
    91         char errModule [256];
    92         if ( (rc = DosLoadModule(
    93             errModule, sizeof(errModule),
    94             QFile::encodeName( filename ).data(), &pHnd
    95         ))) {
     83    QCString filename =
     84        QFile::encodeName( QDir::convertSeparators ( library->library() ) );
     85    if ( map.find(filename) != map.end() ) {
     86        LibInstance *lib = map[filename];
     87        lib->refCount++;
     88        pHnd = lib->module;
     89    } else {
     90        APIRET rc = NO_ERROR;
     91        char errModule [CCHMAXPATH];
     92        if ( (rc = DosLoadModule( errModule, sizeof(errModule),
     93                                  filename.data(), &pHnd
     94        )) != NO_ERROR ) {
    9695            pHnd = 0;
    9796#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
    98             qSystemWarning( QString("Failed to load library %1 (reason: %2)!")
    99                 .arg( filename ).arg( errModule ), rc
     97            qSystemWarning( QString("Failed to load library %1 (reason: %2)!")
     98                .arg( filename.data() ).arg( errModule ), rc
    10099            );
    101100#endif
    102101        }
    103         if ( pHnd ) {
    104             LibInstance *lib = new LibInstance;
    105             lib->module = pHnd;
    106             lib->refCount++;
    107             map->insert( filename, lib );
    108         }
     102        if ( pHnd ) {
     103            LibInstance *lib = new LibInstance;
     104            lib->module = pHnd;
     105            lib->refCount++;
     106            map.insert( filename, lib );
     107        }
    109108    }
    110109    return pHnd != 0;
     
    113112bool QLibraryPrivate::freeLibrary()
    114113{
    115     if ( !pHnd )
    116         return TRUE;
    117 
    118 #ifdef QT_THREAD_SUPPORT
    119     // protect map access
    120     QMutexLocker locker( qt_global_mutexpool ?
    121                          qt_global_mutexpool->get( &map ) : 0 );
    122 #endif // QT_THREAD_SUPPORT
    123 
    124     bool ok = FALSE;
    125     QMap<QString, LibInstance*>::iterator it;
    126     for ( it = map->begin(); it != map->end(); ++it ) {
    127         LibInstance *lib = *it;
    128         if ( lib->module == pHnd ) {
    129             lib->refCount--;
    130             if ( lib->refCount == 0 ) {
    131                 ok = DosFreeModule( pHnd ) == 0;
    132                 if ( ok ) {
    133                     map->remove( it );
    134                     if ( map->count() == 0 ) {
    135                         delete map;
    136                         map = 0;
    137                     }
    138                 }
    139                 delete lib;
    140             } else
    141                 ok = TRUE;
    142             break;
    143         }
    144     }
    145     if ( ok )
    146         pHnd = 0;
    147 #if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
    148     else
    149         qSystemWarning( "Failed to unload library!" );
    150 #endif
    151     return ok;
     114    return derefLib( TRUE );
    152115}
    153116
     
    155118{
    156119    if ( !pHnd )
    157         return 0;
     120        return 0;
    158121
    159     void* address;
    160     if ( DosQueryProcAddr( pHnd, 0, f, (PFN*) &address) ) address = 0;
     122    void *address = 0;
     123    APIRET rc = NO_ERROR;
     124    if ( (rc = DosQueryProcAddr( pHnd, 0, f, (PFN*) &address)) != NO_ERROR )
     125        address = 0;
    161126#if defined(QT_DEBUG_COMPONENT)
    162127    if ( !address )
    163         qSystemWarning( QString("Couldn't resolve symbol \"%1\"").arg( f ) );
     128        qSystemWarning( QString("Couldn't resolve symbol \"%1\"").arg( f ), rc );
    164129#endif
    165130
     
    167132}
    168133
     134bool QLibraryPrivate::derefLib( bool doFree )
     135{
     136    if ( !pHnd )
     137        return TRUE;
     138
     139#ifdef QT_THREAD_SUPPORT
     140    // protect map access
     141    QMutexLocker locker( qt_global_mutexpool ?
     142                         qt_global_mutexpool->get( &map ) : 0 );
     143#endif // QT_THREAD_SUPPORT
     144
     145    APIRET rc = ERROR_INVALID_HANDLE;
     146    LibInstanceMap::iterator it;
     147    for ( it = map.begin(); it != map.end(); ++it ) {
     148        LibInstance *lib = *it;
     149        if ( lib->module == pHnd ) {
     150            lib->refCount--;
     151            if ( lib->refCount == 0 ) {
     152                if ( doFree )
     153                    rc = DosFreeModule( pHnd );
     154                else
     155                    rc = NO_ERROR;
     156                if ( rc == NO_ERROR ) {
     157                    map.remove( it );
     158                    delete lib;
     159                } else
     160                    lib->refCount++;               
     161            } else
     162                rc = NO_ERROR;
     163            break;
     164        }
     165    }
     166    if ( rc == NO_ERROR )
     167        pHnd = 0;
     168#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
     169    else
     170        qSystemWarning( "Failed to unload library!", rc );
     171#endif
     172    return rc == NO_ERROR;
     173}
     174
    169175#endif //QT_NO_LIBRARY
Note: See TracChangeset for help on using the changeset viewer.