@@ -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
@@ -2291,6 +2292,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
22912292 int startup_count = 0 ;
22922293 int shutdown_count = 0 ;
22932294 int post_deactivate_count = 0 ;
2295+ int dl_loaded_count = 0 ;
22942296 zend_class_entry * ce ;
22952297 int class_count = 0 ;
22962298
@@ -2305,6 +2307,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23052307 if (module -> post_deactivate_func ) {
23062308 post_deactivate_count ++ ;
23072309 }
2310+ if (module -> handle ) {
2311+ dl_loaded_count ++ ;
2312+ }
23082313 } ZEND_HASH_FOREACH_END ();
23092314 module_request_startup_handlers = (zend_module_entry * * )realloc (
23102315 module_request_startup_handlers ,
@@ -2317,6 +2322,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23172322 module_request_shutdown_handlers [shutdown_count ] = NULL ;
23182323 module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1 ;
23192324 module_post_deactivate_handlers [post_deactivate_count ] = NULL ;
2325+ /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2326+ modules_dl_loaded = realloc (modules_dl_loaded , sizeof (zend_module_entry * ) * (dl_loaded_count + 1 ));
2327+ modules_dl_loaded [dl_loaded_count ] = NULL ;
23202328 startup_count = 0 ;
23212329
23222330 ZEND_HASH_MAP_FOREACH_PTR (& module_registry , module ) {
@@ -2329,6 +2337,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23292337 if (module -> post_deactivate_func ) {
23302338 module_post_deactivate_handlers [-- post_deactivate_count ] = module ;
23312339 }
2340+ if (module -> handle ) {
2341+ modules_dl_loaded [-- dl_loaded_count ] = module ;
2342+ }
23322343 } ZEND_HASH_FOREACH_END ();
23332344
23342345 /* Collect internal classes with static members */
@@ -3072,18 +3083,23 @@ void module_destructor(zend_module_entry *module) /* {{{ */
30723083 clean_module_functions (module );
30733084 }
30743085
3075- #if HAVE_LIBDL
3076- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3077- DL_UNLOAD (module -> handle );
3078- }
3079- #endif
3080-
30813086#if ZEND_RC_DEBUG
30823087 zend_rc_debug = orig_rc_debug ;
30833088#endif
30843089}
30853090/* }}} */
30863091
3092+ void module_registry_unload (const zend_module_entry * module )
3093+ {
3094+ #if HAVE_LIBDL
3095+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3096+ DL_UNLOAD (module -> handle );
3097+ }
3098+ #else
3099+ ZEND_IGNORE_VALUE (module );
3100+ #endif
3101+ }
3102+
30873103ZEND_API void zend_activate_modules (void ) /* {{{ */
30883104{
30893105 zend_module_entry * * p = module_request_startup_handlers ;
@@ -3128,6 +3144,18 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
31283144}
31293145/* }}} */
31303146
3147+ void zend_unload_modules (void ) /* {{{ */
3148+ {
3149+ zend_module_entry * * modules = modules_dl_loaded ;
3150+ while (* modules ) {
3151+ module_registry_unload (* modules );
3152+ modules ++ ;
3153+ }
3154+ free (modules_dl_loaded );
3155+ modules_dl_loaded = NULL ;
3156+ }
3157+ /* }}} */
3158+
31313159ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
31323160{
31333161 if (EG (full_tables_cleanup )) {
@@ -3146,6 +3174,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
31463174 break ;
31473175 }
31483176 module_destructor (module );
3177+ if (module -> handle ) {
3178+ module_registry_unload (module );
3179+ }
31493180 zend_string_release_ex (key , 0 );
31503181 } ZEND_HASH_MAP_FOREACH_END_DEL ();
31513182 } else {
0 commit comments