@@ -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
@@ -2292,6 +2293,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2292
2293
int startup_count = 0 ;
2293
2294
int shutdown_count = 0 ;
2294
2295
int post_deactivate_count = 0 ;
2296
+ int dl_loaded_count = 0 ;
2295
2297
zend_class_entry * ce ;
2296
2298
int class_count = 0 ;
2297
2299
@@ -2306,6 +2308,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2306
2308
if (module -> post_deactivate_func ) {
2307
2309
post_deactivate_count ++ ;
2308
2310
}
2311
+ if (module -> handle ) {
2312
+ dl_loaded_count ++ ;
2313
+ }
2309
2314
} ZEND_HASH_FOREACH_END ();
2310
2315
module_request_startup_handlers = (zend_module_entry * * )realloc (
2311
2316
module_request_startup_handlers ,
@@ -2318,6 +2323,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2318
2323
module_request_shutdown_handlers [shutdown_count ] = NULL ;
2319
2324
module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1 ;
2320
2325
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 ;
2321
2329
startup_count = 0 ;
2322
2330
2323
2331
ZEND_HASH_MAP_FOREACH_PTR (& module_registry , module ) {
@@ -2330,6 +2338,9 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2330
2338
if (module -> post_deactivate_func ) {
2331
2339
module_post_deactivate_handlers [-- post_deactivate_count ] = module ;
2332
2340
}
2341
+ if (module -> handle ) {
2342
+ modules_dl_loaded [-- dl_loaded_count ] = module ;
2343
+ }
2333
2344
} ZEND_HASH_FOREACH_END ();
2334
2345
2335
2346
/* Collect internal classes with static members */
@@ -3082,7 +3093,7 @@ void module_destructor(zend_module_entry *module) /* {{{ */
3082
3093
void module_registry_unload (const zend_module_entry * module )
3083
3094
{
3084
3095
#if HAVE_LIBDL
3085
- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3096
+ if (!getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3086
3097
DL_UNLOAD (module -> handle );
3087
3098
}
3088
3099
#else
@@ -3134,6 +3145,17 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
3134
3145
}
3135
3146
/* }}} */
3136
3147
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
+
3137
3159
ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
3138
3160
{
3139
3161
if (EG (full_tables_cleanup )) {
@@ -3152,7 +3174,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3152
3174
break ;
3153
3175
}
3154
3176
module_destructor (module );
3155
- module_registry_unload (module );
3177
+ if (module -> handle ) {
3178
+ module_registry_unload (module );
3179
+ }
3156
3180
zend_string_release_ex (key , 0 );
3157
3181
} ZEND_HASH_MAP_FOREACH_END_DEL ();
3158
3182
} else {
0 commit comments