@@ -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 */
@@ -3073,18 +3084,23 @@ void module_destructor(zend_module_entry *module) /* {{{ */
3073
3084
clean_module_functions (module );
3074
3085
}
3075
3086
3076
- #if HAVE_LIBDL
3077
- if (module -> handle && !getenv ("ZEND_DONT_UNLOAD_MODULES" )) {
3078
- DL_UNLOAD (module -> handle );
3079
- }
3080
- #endif
3081
-
3082
3087
#if ZEND_RC_DEBUG
3083
3088
zend_rc_debug = orig_rc_debug ;
3084
3089
#endif
3085
3090
}
3086
3091
/* }}} */
3087
3092
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
+
3088
3104
ZEND_API void zend_activate_modules (void ) /* {{{ */
3089
3105
{
3090
3106
zend_module_entry * * p = module_request_startup_handlers ;
@@ -3129,6 +3145,18 @@ ZEND_API void zend_deactivate_modules(void) /* {{{ */
3129
3145
}
3130
3146
/* }}} */
3131
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
+ modules_dl_loaded = NULL ;
3157
+ }
3158
+ /* }}} */
3159
+
3132
3160
ZEND_API void zend_post_deactivate_modules (void ) /* {{{ */
3133
3161
{
3134
3162
if (EG (full_tables_cleanup )) {
@@ -3147,6 +3175,9 @@ ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3147
3175
break ;
3148
3176
}
3149
3177
module_destructor (module );
3178
+ if (module -> handle ) {
3179
+ module_registry_unload (module );
3180
+ }
3150
3181
zend_string_release_ex (key , 0 );
3151
3182
} ZEND_HASH_MAP_FOREACH_END_DEL ();
3152
3183
} else {
0 commit comments