File tree 4 files changed +43
-2
lines changed
4 files changed +43
-2
lines changed Original file line number Diff line number Diff line change @@ -199,6 +199,8 @@ impl Library {
199
199
/// You only need to call this if you are interested in handling any errors that may arise when
200
200
/// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
201
201
/// library and ignore the errors were they arise.
202
+ ///
203
+ /// The underlying data structures may still get leaked if an error does occur.
202
204
pub fn close ( self ) -> Result < ( ) , Error > {
203
205
self . 0 . close ( )
204
206
}
Original file line number Diff line number Diff line change @@ -301,6 +301,8 @@ impl Library {
301
301
///
302
302
/// You only need to call this if you are interested in handling any errors that may arise when
303
303
/// library is unloaded. Otherwise this will be done when `Library` is dropped.
304
+ ///
305
+ /// The underlying data structures may still get leaked if an error does occur.
304
306
pub fn close ( self ) -> Result < ( ) , crate :: Error > {
305
307
let result = with_dlerror ( |desc| crate :: Error :: DlClose { desc } , || {
306
308
if unsafe { dlclose ( self . handle ) } == 0 {
@@ -309,6 +311,9 @@ impl Library {
309
311
None
310
312
}
311
313
} ) . map_err ( |e| e. unwrap_or ( crate :: Error :: DlCloseUnknown ) ) ;
314
+ // While the library is not free'd yet in case of an error, there is no reason to try
315
+ // dropping it again, because all that will do is try calling `FreeLibrary` again. only
316
+ // this time it would ignore the return result, which we already seen failing…
312
317
std:: mem:: forget ( self ) ;
313
318
result
314
319
}
Original file line number Diff line number Diff line change @@ -217,14 +217,24 @@ impl Library {
217
217
}
218
218
219
219
/// Unload the library.
220
+ ///
221
+ /// You only need to call this if you are interested in handling any errors that may arise when
222
+ /// library is unloaded. Otherwise this will be done when `Library` is dropped.
223
+ ///
224
+ /// The underlying data structures may still get leaked if an error does occur.
220
225
pub fn close ( self ) -> Result < ( ) , crate :: Error > {
221
- with_get_last_error ( |source| crate :: Error :: FreeLibrary { source } , || {
226
+ let result = with_get_last_error ( |source| crate :: Error :: FreeLibrary { source } , || {
222
227
if unsafe { libloaderapi:: FreeLibrary ( self . 0 ) == 0 } {
223
228
None
224
229
} else {
225
230
Some ( ( ) )
226
231
}
227
- } ) . map_err ( |e| e. unwrap_or ( crate :: Error :: FreeLibraryUnknown ) )
232
+ } ) . map_err ( |e| e. unwrap_or ( crate :: Error :: FreeLibraryUnknown ) ) ;
233
+ // While the library is not free'd yet in case of an error, there is no reason to try
234
+ // dropping it again, because all that will do is try calling `FreeLibrary` again. only
235
+ // this time it would ignore the return result, which we already seen failing…
236
+ std:: mem:: forget ( self ) ;
237
+ result
228
238
}
229
239
}
230
240
Original file line number Diff line number Diff line change @@ -145,6 +145,30 @@ fn test_static_ptr() {
145
145
}
146
146
}
147
147
148
+ #[ test]
149
+ // Something about i686-pc-windows-gnu, makes dll initialization code call abort when it is loaded
150
+ // and unloaded many times. So far it seems like an issue with mingw, not libloading, so ignoring
151
+ // the target. Especially since it is very unlikely to be fixed given the state of support its
152
+ // support.
153
+ #[ cfg( not( all( target_arch="x86" , target_os="windows" , target_env="gnu" ) ) ) ]
154
+ fn manual_close_many_times ( ) {
155
+ make_helpers ( ) ;
156
+ let join_handles: Vec < _ > = ( 0 ..16 ) . map ( |_| {
157
+ std:: thread:: spawn ( || unsafe {
158
+ for _ in 0 ..10000 {
159
+ let lib = Library :: new ( LIBPATH ) . expect ( "open library" ) ;
160
+ let _: Symbol < unsafe extern fn ( u32 ) -> u32 > =
161
+ lib. get ( b"test_identity_u32" ) . expect ( "get fn" ) ;
162
+ lib. close ( ) . expect ( "close is successful" ) ;
163
+ }
164
+ } )
165
+ } ) . collect ( ) ;
166
+ for handle in join_handles {
167
+ handle. join ( ) . expect ( "thread should succeed" ) ;
168
+ }
169
+ }
170
+
171
+
148
172
#[ cfg( unix) ]
149
173
#[ test]
150
174
fn library_this_get ( ) {
You can’t perform that action at this time.
0 commit comments