@@ -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
@@ -2368,6 +2369,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2368
2369
int startup_count = 0 ;
2369
2370
int shutdown_count = 0 ;
2370
2371
int post_deactivate_count = 0 ;
2372
+ int dl_loaded_count = 0 ;
2371
2373
zend_class_entry * ce ;
2372
2374
int class_count = 0 ;
2373
2375
@@ -2382,6 +2384,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2382
2384
if (module -> post_deactivate_func ) {
2383
2385
post_deactivate_count ++ ;
2384
2386
}
2387
+ if (module -> handle ) {
2388
+ dl_loaded_count ++ ;
2389
+ }
2385
2390
} ZEND_HASH_FOREACH_END ();
2386
2391
module_request_startup_handlers = (zend_module_entry * * )realloc (
2387
2392
module_request_startup_handlers ,
@@ -2394,6 +2399,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2394
2399
module_request_shutdown_handlers [shutdown_count ] = NULL ;
2395
2400
module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1 ;
2396
2401
module_post_deactivate_handlers [post_deactivate_count ] = NULL ;
2402
+ /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2403
+ modules_dl_loaded = realloc (modules_dl_loaded , sizeof (zend_module_entry * ) * (dl_loaded_count + 1 ));
2404
+ modules_dl_loaded [dl_loaded_count ] = NULL ;
2397
2405
startup_count = 0 ;
2398
2406
2399
2407
ZEND_HASH_MAP_FOREACH_PTR (& module_registry , module ) {
@@ -2406,6 +2414,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2406
2414
if (module -> post_deactivate_func ) {
2407
2415
module_post_deactivate_handlers [-- post_deactivate_count ] = module ;
2408
2416
}
2417
+ if (module -> handle ) {
2418
+ modules_dl_loaded [-- dl_loaded_count ] = module ;
2419
+ }
2409
2420
} ZEND_HASH_FOREACH_END ();
2410
2421
2411
2422
/* Collect internal classes with static members */
@@ -3180,18 +3191,23 @@ void module_destructor(zend_module_entry *module) /* {{{ */
3180
3191
clean_module_functions (module );
3181
3192
}
3182
3193
3183
- #if HAVE_LIBDL
3184
- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3185
- DL_UNLOAD (module -> handle );
3186
- }
3187
- #endif
3188
-
3189
3194
#if ZEND_RC_DEBUG
3190
3195
zend_rc_debug = orig_rc_debug ;
3191
3196
#endif
3192
3197
}
3193
3198
/* }}} */
3194
3199
3200
+ void module_registry_unload (const zend_module_entry * module )
3201
+ {
3202
+ #if HAVE_LIBDL
3203
+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3204
+ DL_UNLOAD (module -> handle );
3205
+ }
3206
+ #else
3207
+ ZEND_IGNORE_VALUE (module );
3208
+ #endif
3209
+ }
3210
+
3195
3211
ZEND_API void zend_activate_modules (void ) /* {{{ */
3196
3212
{
3197
3213
zend_module_entry * * p = module_request_startup_handlers ;
@@ -3236,6 +3252,18 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
3236
3252
}
3237
3253
/* }}} */
3238
3254
3255
+ void zend_unload_modules (void ) /* {{{ */
3256
+ {
3257
+ zend_module_entry * * modules = modules_dl_loaded ;
3258
+ while (* modules ) {
3259
+ module_registry_unload (* modules );
3260
+ modules ++ ;
3261
+ }
3262
+ free (modules_dl_loaded );
3263
+ modules_dl_loaded = NULL ;
3264
+ }
3265
+ /* }}} */
3266
+
3239
3267
ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
3240
3268
{
3241
3269
if (EG (full_tables_cleanup )) {
@@ -3254,6 +3282,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3254
3282
break ;
3255
3283
}
3256
3284
module_destructor (module );
3285
+ if (module -> handle ) {
3286
+ module_registry_unload (module );
3287
+ }
3257
3288
zend_string_release_ex (key , 0 );
3258
3289
} ZEND_HASH_MAP_FOREACH_END_DEL ();
3259
3290
} else {
0 commit comments