@@ -41,6 +41,7 @@ ZEND_API HashTable module_registry;
41
41
static zend_module_entry * * module_request_startup_handlers ;
42
42
static zend_module_entry * * module_request_shutdown_handlers ;
43
43
static zend_module_entry * * module_post_deactivate_handlers ;
44
+ static zend_module_entry * * modules_dl_loaded ;
44
45
45
46
static zend_class_entry * * class_cleanup_handlers ;
46
47
@@ -2398,6 +2399,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2398
2399
int startup_count = 0 ;
2399
2400
int shutdown_count = 0 ;
2400
2401
int post_deactivate_count = 0 ;
2402
+ int dl_loaded_count = 0 ;
2401
2403
zend_class_entry * ce ;
2402
2404
int class_count = 0 ;
2403
2405
@@ -2412,6 +2414,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2412
2414
if (module -> post_deactivate_func ) {
2413
2415
post_deactivate_count ++ ;
2414
2416
}
2417
+ if (module -> handle ) {
2418
+ dl_loaded_count ++ ;
2419
+ }
2415
2420
} ZEND_HASH_FOREACH_END ();
2416
2421
module_request_startup_handlers = (zend_module_entry * * )realloc (
2417
2422
module_request_startup_handlers ,
@@ -2424,6 +2429,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2424
2429
module_request_shutdown_handlers [shutdown_count ] = NULL ;
2425
2430
module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1 ;
2426
2431
module_post_deactivate_handlers [post_deactivate_count ] = NULL ;
2432
+ /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2433
+ modules_dl_loaded = realloc (modules_dl_loaded , sizeof (zend_module_entry * ) * (dl_loaded_count + 1 ));
2434
+ modules_dl_loaded [dl_loaded_count ] = NULL ;
2427
2435
startup_count = 0 ;
2428
2436
2429
2437
ZEND_HASH_MAP_FOREACH_PTR (& module_registry , module ) {
@@ -2436,6 +2444,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2436
2444
if (module -> post_deactivate_func ) {
2437
2445
module_post_deactivate_handlers [-- post_deactivate_count ] = module ;
2438
2446
}
2447
+ if (module -> handle ) {
2448
+ modules_dl_loaded [-- dl_loaded_count ] = module ;
2449
+ }
2439
2450
} ZEND_HASH_FOREACH_END ();
2440
2451
2441
2452
/* Collect internal classes with static members */
@@ -3238,18 +3249,23 @@ void module_destructor(zend_module_entry *module) /* {{{ */
3238
3249
clean_module_functions (module );
3239
3250
}
3240
3251
3241
- #if HAVE_LIBDL
3242
- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3243
- DL_UNLOAD (module -> handle );
3244
- }
3245
- #endif
3246
-
3247
3252
#if ZEND_RC_DEBUG
3248
3253
zend_rc_debug = orig_rc_debug ;
3249
3254
#endif
3250
3255
}
3251
3256
/* }}} */
3252
3257
3258
+ void module_registry_unload (const zend_module_entry * module )
3259
+ {
3260
+ #if HAVE_LIBDL
3261
+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3262
+ DL_UNLOAD (module -> handle );
3263
+ }
3264
+ #else
3265
+ ZEND_IGNORE_VALUE (module );
3266
+ #endif
3267
+ }
3268
+
3253
3269
ZEND_API void zend_activate_modules (void ) /* {{{ */
3254
3270
{
3255
3271
zend_module_entry * * p = module_request_startup_handlers ;
@@ -3294,6 +3310,18 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
3294
3310
}
3295
3311
/* }}} */
3296
3312
3313
+ void zend_unload_modules (void ) /* {{{ */
3314
+ {
3315
+ zend_module_entry * * modules = modules_dl_loaded ;
3316
+ while (* modules ) {
3317
+ module_registry_unload (* modules );
3318
+ modules ++ ;
3319
+ }
3320
+ free (modules_dl_loaded );
3321
+ modules_dl_loaded = NULL ;
3322
+ }
3323
+ /* }}} */
3324
+
3297
3325
ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
3298
3326
{
3299
3327
if (EG (full_tables_cleanup )) {
@@ -3312,6 +3340,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3312
3340
break ;
3313
3341
}
3314
3342
module_destructor (module );
3343
+ if (module -> handle ) {
3344
+ module_registry_unload (module );
3345
+ }
3315
3346
zend_string_release_ex (key , 0 );
3316
3347
} ZEND_HASH_MAP_FOREACH_END_DEL ();
3317
3348
} else {
0 commit comments