@@ -40,6 +40,7 @@ ZEND_API HashTable module_registry;
4040static zend_module_entry * * module_request_startup_handlers ;
4141static zend_module_entry * * module_request_shutdown_handlers ;
4242static zend_module_entry * * module_post_deactivate_handlers ;
43+ static zend_module_entry * * modules_dl_loaded ;
4344
4445static zend_class_entry * * class_cleanup_handlers ;
4546
@@ -2367,6 +2368,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23672368 int startup_count = 0 ;
23682369 int shutdown_count = 0 ;
23692370 int post_deactivate_count = 0 ;
2371+ int dl_loaded_count = 0 ;
23702372 zend_class_entry * ce ;
23712373 int class_count = 0 ;
23722374
@@ -2381,6 +2383,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23812383 if (module -> post_deactivate_func ) {
23822384 post_deactivate_count ++ ;
23832385 }
2386+ if (module -> handle ) {
2387+ dl_loaded_count ++ ;
2388+ }
23842389 } ZEND_HASH_FOREACH_END ();
23852390 module_request_startup_handlers = (zend_module_entry * * )realloc (
23862391 module_request_startup_handlers ,
@@ -2393,6 +2398,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23932398 module_request_shutdown_handlers [shutdown_count ] = NULL ;
23942399 module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1 ;
23952400 module_post_deactivate_handlers [post_deactivate_count ] = NULL ;
2401+ /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2402+ modules_dl_loaded = realloc (modules_dl_loaded , sizeof (zend_module_entry * ) * (dl_loaded_count + 1 ));
2403+ modules_dl_loaded [dl_loaded_count ] = NULL ;
23962404 startup_count = 0 ;
23972405
23982406 ZEND_HASH_MAP_FOREACH_PTR (& module_registry , module ) {
@@ -2405,6 +2413,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
24052413 if (module -> post_deactivate_func ) {
24062414 module_post_deactivate_handlers [-- post_deactivate_count ] = module ;
24072415 }
2416+ if (module -> handle ) {
2417+ modules_dl_loaded [-- dl_loaded_count ] = module ;
2418+ }
24082419 } ZEND_HASH_FOREACH_END ();
24092420
24102421 /* Collect internal classes with static members */
@@ -3179,18 +3190,23 @@ void module_destructor(zend_module_entry *module) /* {{{ */
31793190 clean_module_functions (module );
31803191 }
31813192
3182- #if HAVE_LIBDL
3183- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3184- DL_UNLOAD (module -> handle );
3185- }
3186- #endif
3187-
31883193#if ZEND_RC_DEBUG
31893194 zend_rc_debug = orig_rc_debug ;
31903195#endif
31913196}
31923197/* }}} */
31933198
3199+ void module_registry_unload (const zend_module_entry * module )
3200+ {
3201+ #if HAVE_LIBDL
3202+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3203+ DL_UNLOAD (module -> handle );
3204+ }
3205+ #else
3206+ ZEND_IGNORE_VALUE (module );
3207+ #endif
3208+ }
3209+
31943210ZEND_API void zend_activate_modules (void ) /* {{{ */
31953211{
31963212 zend_module_entry * * p = module_request_startup_handlers ;
@@ -3235,6 +3251,18 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
32353251}
32363252/* }}} */
32373253
3254+ void zend_unload_modules (void ) /* {{{ */
3255+ {
3256+ zend_module_entry * * modules = modules_dl_loaded ;
3257+ while (* modules ) {
3258+ module_registry_unload (* modules );
3259+ modules ++ ;
3260+ }
3261+ free (modules_dl_loaded );
3262+ modules_dl_loaded = NULL ;
3263+ }
3264+ /* }}} */
3265+
32383266ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
32393267{
32403268 if (EG (full_tables_cleanup )) {
@@ -3253,6 +3281,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
32533281 break ;
32543282 }
32553283 module_destructor (module );
3284+ if (module -> handle ) {
3285+ module_registry_unload (module );
3286+ }
32563287 zend_string_release_ex (key , 0 );
32573288 } ZEND_HASH_MAP_FOREACH_END_DEL ();
32583289 } else {
0 commit comments