@@ -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 */
@@ -3082,7 +3093,7 @@ void module_destructor(zend_module_entry *module) /* {{{ */
30823093void module_registry_unload (const zend_module_entry * module )
30833094{
30843095#if HAVE_LIBDL
3085- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3096+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
30863097 DL_UNLOAD (module -> handle );
30873098 }
30883099#else
@@ -3134,6 +3145,17 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
31343145}
31353146/* }}} */
31363147
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+ }
3157+ /* }}} */
3158+
31373159ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
31383160{
31393161 if (EG (full_tables_cleanup )) {
@@ -3152,7 +3174,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
31523174 break ;
31533175 }
31543176 module_destructor (module );
3155- module_registry_unload (module );
3177+ if (module -> handle ) {
3178+ module_registry_unload (module );
3179+ }
31563180 zend_string_release_ex (key , 0 );
31573181 } ZEND_HASH_MAP_FOREACH_END_DEL ();
31583182 } else {
0 commit comments