@@ -41,6 +41,7 @@ ZEND_API HashTable module_registry;
4141static zend_module_entry * * module_request_startup_handlers ;
4242static zend_module_entry * * module_request_shutdown_handlers ;
4343static zend_module_entry * * module_post_deactivate_handlers ;
44+ static zend_module_entry * * modules_dl_loaded ;
4445
4546static zend_class_entry * * class_cleanup_handlers ;
4647
@@ -2292,6 +2293,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
22922293 int startup_count = 0 ;
22932294 int shutdown_count = 0 ;
22942295 int post_deactivate_count = 0 ;
2296+ int dl_loaded_count = 0 ;
22952297 zend_class_entry * ce ;
22962298 int class_count = 0 ;
22972299
@@ -2306,6 +2308,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23062308 if (module -> post_deactivate_func ) {
23072309 post_deactivate_count ++ ;
23082310 }
2311+ if (module -> handle ) {
2312+ dl_loaded_count ++ ;
2313+ }
23092314 } ZEND_HASH_FOREACH_END ();
23102315 module_request_startup_handlers = (zend_module_entry * * )realloc (
23112316 module_request_startup_handlers ,
@@ -2318,6 +2323,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23182323 module_request_shutdown_handlers [shutdown_count ] = NULL ;
23192324 module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1 ;
23202325 module_post_deactivate_handlers [post_deactivate_count ] = NULL ;
2326+ /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2327+ modules_dl_loaded = realloc (modules_dl_loaded , sizeof (zend_module_entry * ) * (dl_loaded_count + 1 ));
2328+ modules_dl_loaded [dl_loaded_count ] = NULL ;
23212329 startup_count = 0 ;
23222330
23232331 ZEND_HASH_MAP_FOREACH_PTR (& module_registry , module ) {
@@ -2330,6 +2338,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
23302338 if (module -> post_deactivate_func ) {
23312339 module_post_deactivate_handlers [-- post_deactivate_count ] = module ;
23322340 }
2341+ if (module -> handle ) {
2342+ modules_dl_loaded [-- dl_loaded_count ] = module ;
2343+ }
23332344 } ZEND_HASH_FOREACH_END ();
23342345
23352346 /* Collect internal classes with static members */
@@ -3073,18 +3084,23 @@ void module_destructor(zend_module_entry *module) /* {{{ */
30733084 clean_module_functions (module );
30743085 }
30753086
3076- #if HAVE_LIBDL
3077- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3078- DL_UNLOAD (module -> handle );
3079- }
3080- #endif
3081-
30823087#if ZEND_RC_DEBUG
30833088 zend_rc_debug = orig_rc_debug ;
30843089#endif
30853090}
30863091/* }}} */
30873092
3093+ void module_registry_unload (const zend_module_entry * module )
3094+ {
3095+ #if HAVE_LIBDL
3096+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3097+ DL_UNLOAD (module -> handle );
3098+ }
3099+ #else
3100+ ZEND_IGNORE_VALUE (module );
3101+ #endif
3102+ }
3103+
30883104ZEND_API void zend_activate_modules (void ) /* {{{ */
30893105{
30903106 zend_module_entry * * p = module_request_startup_handlers ;
@@ -3129,6 +3145,18 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
31293145}
31303146/* }}} */
31313147
3148+ void zend_unload_modules (void ) /* {{{ */
3149+ {
3150+ zend_module_entry * * modules = modules_dl_loaded ;
3151+ while (* modules ) {
3152+ module_registry_unload (* modules );
3153+ modules ++ ;
3154+ }
3155+ free (modules_dl_loaded );
3156+ modules_dl_loaded = NULL ;
3157+ }
3158+ /* }}} */
3159+
31323160ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
31333161{
31343162 if (EG (full_tables_cleanup )) {
@@ -3147,6 +3175,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
31473175 break ;
31483176 }
31493177 module_destructor (module );
3178+ if (module -> handle ) {
3179+ module_registry_unload (module );
3180+ }
31503181 zend_string_release_ex (key , 0 );
31513182 } ZEND_HASH_MAP_FOREACH_END_DEL ();
31523183 } else {
0 commit comments