source: trunk/src/tools/qlibrary_pm.cpp

Last change on this file was 156, checked in by dmik, 19 years ago

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.
  • Property svn:keywords set to Id
File size: 5.1 KB
RevLine 
[8]1/****************************************************************************
2** $Id: qlibrary_pm.cpp 156 2006-11-15 01:45:23Z dmik $
3**
4** Implementation of QLibraryPrivate class for Win32
5**
6** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
7** Copyright (C) 2004 Norman ASA. Initial OS/2 Port.
8** Copyright (C) 2005 netlabs.org. Further OS/2 Development.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include <qmap.h>
39#include <private/qlibrary_p.h>
40
41#ifdef QT_THREAD_SUPPORT
42# include <private/qmutexpool_p.h>
43#endif // QT_THREAD_SUPPORT
44
45#ifndef QT_H
46#include "qfile.h"
[156]47#include "qdir.h"
[8]48#endif // QT_H
49
50#ifndef QT_NO_LIBRARY
51
52struct LibInstance {
53 LibInstance() { module = 0; refCount = 0; }
54 HMODULE module;
55 int refCount;
56};
57
[156]58typedef QMap<QCString, LibInstance*> LibInstanceMap;
59
60static LibInstanceMap map;
[8]61/*
62 The platform dependent implementations of
63 - loadLibrary
64 - freeLibrary
65 - resolveSymbol
66
67 It's not too hard to guess what the functions do.
68*/
69
70#include "qt_os2.h"
71
72bool QLibraryPrivate::loadLibrary()
73{
74 if ( pHnd )
[156]75 return TRUE;
[8]76
77#ifdef QT_THREAD_SUPPORT
78 // protect map creation/access
79 QMutexLocker locker( qt_global_mutexpool ?
[156]80 qt_global_mutexpool->get( &map ) : 0 );
[8]81#endif // QT_THREAD_SUPPORT
82
[156]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 ) {
[8]95 pHnd = 0;
96#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
[156]97 qSystemWarning( QString("Failed to load library %1 (reason: %2)!")
98 .arg( filename.data() ).arg( errModule ), rc
[8]99 );
100#endif
101 }
[156]102 if ( pHnd ) {
103 LibInstance *lib = new LibInstance;
104 lib->module = pHnd;
105 lib->refCount++;
106 map.insert( filename, lib );
107 }
[8]108 }
109 return pHnd != 0;
110}
111
112bool QLibraryPrivate::freeLibrary()
113{
[156]114 return derefLib( TRUE );
115}
116
117void* QLibraryPrivate::resolveSymbol( const char* f )
118{
[8]119 if ( !pHnd )
[156]120 return 0;
[8]121
[156]122 void *address = 0;
123 APIRET rc = NO_ERROR;
124 if ( (rc = DosQueryProcAddr( pHnd, 0, f, (PFN*) &address)) != NO_ERROR )
125 address = 0;
126#if defined(QT_DEBUG_COMPONENT)
127 if ( !address )
128 qSystemWarning( QString("Couldn't resolve symbol \"%1\"").arg( f ), rc );
129#endif
130
131 return address;
132}
133
134bool QLibraryPrivate::derefLib( bool doFree )
135{
136 if ( !pHnd )
137 return TRUE;
138
[8]139#ifdef QT_THREAD_SUPPORT
140 // protect map access
141 QMutexLocker locker( qt_global_mutexpool ?
[156]142 qt_global_mutexpool->get( &map ) : 0 );
[8]143#endif // QT_THREAD_SUPPORT
144
[156]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 }
[8]165 }
[156]166 if ( rc == NO_ERROR )
167 pHnd = 0;
[8]168#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
169 else
[156]170 qSystemWarning( "Failed to unload library!", rc );
[8]171#endif
[156]172 return rc == NO_ERROR;
[8]173}
174
175#endif //QT_NO_LIBRARY
Note: See TracBrowser for help on using the repository browser.