php 启动过程 - reqeust RSHUTDOWN 过程
概述
request RSHUTDOWN 过程在请求结束后调用
调用触发
- 同 request RINIT 过程一样, 先是用 apache 注册的钩子函数 php_handler 处理请求
- 执行 request RINIT 过程
- 执行 request execute 过程
- 调用 php_apache_request_dtor 开始进行 request RSHUTDOWN 过程
调用过程
-
php_handler 处理完请求后, 调用 php_apache_request_dtor 函数进行 request RSHUTDOWN 过程
-
static int php_handler(request_rec *r) { // 省略 ... if (!parent_req) { // 销毁释放请求 php_apache_request_dtor(r TSRMLS_CC); ctx->request_processed = 1; bucket = apr_bucket_eos_create(r->connection->bucket_alloc); APR_BRIGADE_INSERT_TAIL(brigade, bucket); rv = ap_pass_brigade(r->output_filters, brigade); if (rv != APR_SUCCESS || r->connection->aborted) { zend_first_try { php_handle_aborted_connection(); } zend_end_try(); } apr_brigade_cleanup(brigade); apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup); } else { ctx->r = parent_req; } return OK; } -
调用 php_apache_request_dtor
static void php_apache_request_dtor(request_rec *r TSRMLS_DC) { php_request_shutdown(NULL); }-
调用 php_request_shutdown 函数
-
void php_request_shutdown(void *dummy) { zend_bool report_memleaks; TSRMLS_FETCH(); // 内存泄漏信息 report_memleaks = PG(report_memleaks); // 设置 opcode 执行相关变量为空 EG(opline_ptr) = NULL; EG(active_op_array) = NULL; // 销毁 tick 相关 php_deactivate_ticks(TSRMLS_C); // 调用 register_shutdown_function 注册的 shutdown 函数 if (PG(modules_activated)) zend_try { php_call_shutdown_functions(TSRMLS_C); } zend_end_try(); // 调用析构函数 zend_try { zend_call_destructors(TSRMLS_C); } zend_end_try(); // flush 输出缓冲区 zend_try { zend_bool send_buffer = SG(request_info).headers_only ? 0 : 1; if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR && (size_t)PG(memory_limit) < zend_memory_usage(1 TSRMLS_CC) ) { send_buffer = 0; } if (!send_buffer) { php_output_discard_all(TSRMLS_C); } else { php_output_end_all(TSRMLS_C); } } zend_end_try(); // 重置 max_execution_time zend_try { zend_unset_timeout(TSRMLS_C); } zend_end_try(); // 调用各子模块的 RSHUTDOWN 函数 if (PG(modules_activated)) { zend_deactivate_modules(TSRMLS_C); php_free_shutdown_functions(TSRMLS_C); } // 关闭 output zend_try { php_output_deactivate(TSRMLS_C); } zend_end_try(); // 销毁 PG(http_globals) zend_try { int i; for (i=0; i<NUM_TRACK_VARS; i++) { if (PG(http_globals)[i]) { zval_ptr_dtor(&PG(http_globals)[i]); } } } zend_end_try(); // 释放错误信息 if (PG(last_error_message)) { free(PG(last_error_message)); PG(last_error_message) = NULL; } if (PG(last_error_file)) { free(PG(last_error_file)); PG(last_error_file) = NULL; } // 关闭临时目录 php_shutdown_temporary_directory(); // 关闭 扫描器, 执行器, 编译器, 初始化 ini_entries zend_deactivate(TSRMLS_C); // 调用各子模块的 post_deactivate_func 函数 zend_try { zend_post_deactivate_modules(TSRMLS_C); } zend_end_try(); // 关闭 sapi zend_try { sapi_deactivate(TSRMLS_C); } zend_end_try(); /* 10. Destroy stream hashes */ zend_try { php_shutdown_stream_hashes(TSRMLS_C); } zend_end_try(); // 关闭内存管理器 zend_try { shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0 TSRMLS_CC); } zend_end_try(); zend_interned_strings_restore(TSRMLS_C); // 重置 max_execution_time zend_try { zend_unset_timeout(TSRMLS_C); } zend_end_try(); #ifdef PHP_WIN32 if (PG(com_initialized)) { CoUninitialize(); PG(com_initialized) = 0; } #endif #ifdef HAVE_DTRACE DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method)); #endif /* HAVE_DTRACE */ } -
php_call_shutdown_functions, 调用 register_shutdown_function 注册的 shutdown 函数
void php_call_shutdown_functions(TSRMLS_D) { if (BG(user_shutdown_function_names)) { zend_try { zend_hash_apply(BG(user_shutdown_function_names), (apply_func_t) user_shutdown_function_call TSRMLS_CC); } zend_end_try(); php_free_shutdown_functions(TSRMLS_C); } }-
调用 zend_hash_apply, 实际上是对 BG(user_shutdown_function_names) 循环调用 user_shutdown_function_call 函数
-
ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC) { Bucket *p; IS_CONSISTENT(ht); HASH_PROTECT_RECURSION(ht); p = ht->pListHead; while (p != NULL) { int result = apply_func(p->pData TSRMLS_CC); if (result & ZEND_HASH_APPLY_REMOVE) { p = zend_hash_apply_deleter(ht, p); } else { p = p->pListNext; } if (result & ZEND_HASH_APPLY_STOP) { break; } } HASH_UNPROTECT_RECURSION(ht); } -
user_shutdown_function_call 函数
static int user_shutdown_function_call(php_shutdown_function_entry *shutdown_function_entry TSRMLS_DC) { zval retval; char *function_name; if (!zend_is_callable(shutdown_function_entry->arguments[0], 0, &function_name TSRMLS_CC)) { php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", function_name); if (function_name) { efree(function_name); } return 0; } if (function_name) { efree(function_name); } if (call_user_function(EG(function_table), NULL, shutdown_function_entry->arguments[0], &retval, shutdown_function_entry->arg_count - 1, shutdown_function_entry->arguments + 1 TSRMLS_CC ) == SUCCESS) { zval_dtor(&retval); } return 0; }
-
-
-
zend_call_destructors, 调用各变量的析构函数 __destruct
void zend_call_destructors(TSRMLS_D) { zend_try { shutdown_destructors(TSRMLS_C); } zend_end_try(); }-
调用 shutdown_destructors 函数
-
void shutdown_destructors(TSRMLS_D) /* {{{ */ { zend_try { int symbols; do { symbols = zend_hash_num_elements(&EG(symbol_table)); zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor TSRMLS_CC); } while (symbols != zend_hash_num_elements(&EG(symbol_table))); zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); } zend_catch { /* if we couldn't destruct cleanly, mark all objects as destructed anyway */ zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); } zend_end_try(); } -
zend_hash_reverse_apply 对 EG(symbol_table) 循环调用 zval_call_destructor 函数
static int zval_call_destructor(zval **zv TSRMLS_DC) { if (Z_TYPE_PP(zv) == IS_OBJECT && Z_REFCOUNT_PP(zv) == 1) { return ZEND_HASH_APPLY_REMOVE; } else { return ZEND_HASH_APPLY_KEEP; } } -
调用 zend_objects_store_call_destructors, 调用各变量的析构函数
ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC) { zend_uint i = 1; for (i = 1; i < objects->top ; i++) { if (objects->object_buckets[i].valid) { struct _store_object *obj = &objects->object_buckets[i].bucket.obj; if (!objects->object_buckets[i].destructor_called) { objects->object_buckets[i].destructor_called = 1; if (obj->dtor && obj->object) { obj->refcount++; // 调用析构函数 obj->dtor(obj->object, i TSRMLS_CC); obj = &objects->object_buckets[i].bucket.obj; obj->refcount--; if (obj->refcount == 0) { GC_REMOVE_ZOBJ_FROM_BUFFER(obj); } } } } } }
-
-
-
php_output_discard_all 或者 php_output_end_all, flush 输出缓冲区 (在后续对输出功能做讲解时在详细展开)
-
zend_deactivate_modules, 调用各子模块的 RSHUTDOWN 函数
void zend_deactivate_modules(TSRMLS_D) { EG(opline_ptr) = NULL; /* we're no longer executing anything */ zend_try { if (EG(full_tables_cleanup)) { // 若全部清除, 则对 module_registry 循环调用 module_registry_cleanup 来循环调用 各子模块的 request_shutdown_func 函数 zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC); } else { zend_module_entry **p = module_request_shutdown_handlers; while (*p) { zend_module_entry *module = *p; // 循环调用各子模块的 request_shutdown_func 函数 module->request_shutdown_func(module->type, module->module_number TSRMLS_CC); p++; } } } zend_end_try(); } -
php_output_deactivate, 关闭 output, 释放所有 handler
PHPAPI void php_output_deactivate(TSRMLS_D) { php_output_handler **handler = NULL; if ((OG(flags) & PHP_OUTPUT_ACTIVATED)) { php_output_header(TSRMLS_C); OG(flags) ^= PHP_OUTPUT_ACTIVATED; OG(active) = NULL; OG(running) = NULL; // 释放 handlers if (OG(handlers).elements) { while (SUCCESS == zend_stack_top(&OG(handlers), (void *) &handler)) { php_output_handler_free(handler TSRMLS_CC); zend_stack_del_top(&OG(handlers)); } zend_stack_destroy(&OG(handlers)); } } } -
销毁超全局变量
zend_try { int i; // 循环释放 PG(http_globals) for (i=0; i<NUM_TRACK_VARS; i++) { if (PG(http_globals)[i]) { zval_ptr_dtor(&PG(http_globals)[i]); } } } zend_end_try(); -
zend_deactivate, 关闭扫描器, 执行器, 编译器, 重置 ini_entries
void zend_deactivate(TSRMLS_D) { /* we're no longer executing anything */ EG(opline_ptr) = NULL; EG(active_symbol_table) = NULL; zend_try { shutdown_scanner(TSRMLS_C); } zend_end_try(); // 调用各扩展的 deactivate 方法 shutdown_executor(TSRMLS_C); zend_try { // 销毁编译器 shutdown_compiler(TSRMLS_C); } zend_end_try(); zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC); #ifdef ZEND_DEBUG if (GC_G(gc_enabled) && !CG(unclean_shutdown)) { gc_collect_cycles(TSRMLS_C); } #endif #if GC_BENCH fprintf(stderr, "GC Statistics\n"); fprintf(stderr, "-------------\n"); fprintf(stderr, "Runs: %d\n", GC_G(gc_runs)); fprintf(stderr, "Collected: %d\n", GC_G(collected)); fprintf(stderr, "Root buffer length: %d\n", GC_G(root_buf_length)); fprintf(stderr, "Root buffer peak: %d\n\n", GC_G(root_buf_peak)); fprintf(stderr, " Possible Remove from Marked\n"); fprintf(stderr, " Root Buffered buffer grey\n"); fprintf(stderr, " -------- -------- ----------- ------\n"); fprintf(stderr, "ZVAL %8d %8d %9d %8d\n", GC_G(zval_possible_root), GC_G(zval_buffered), GC_G(zval_remove_from_buffer), GC_G(zval_marked_grey)); fprintf(stderr, "ZOBJ %8d %8d %9d %8d\n", GC_G(zobj_possible_root), GC_G(zobj_buffered), GC_G(zobj_remove_from_buffer), GC_G(zobj_marked_grey)); #endif zend_try { // 调用 zend_ini_entry 的 on_modify 函数 // 释放 ini_entry 的值 zend_ini_deactivate(TSRMLS_C); } zend_end_try(); } -
zend_post_deactivate_modules, 调用各子模块的 post_deactivate_func 函数
void zend_post_deactivate_modules(TSRMLS_D) { if (EG(full_tables_cleanup)) { zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC); zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_unload_temp TSRMLS_CC); } else { zend_module_entry **p = module_post_deactivate_handlers; // 循环调用各模块的 post_deactivate_func 函数 while (*p) { zend_module_entry *module = *p; module->post_deactivate_func(); p++; } } } -
sapi_deactivate, 关闭 sapi, 释放 sapi 相关的结构体
-
shutdown_memory_manager, 关闭内存管理器
-
-
-
总结
request RSHUTDOWN 过程在每次请求结束后均会调用
主要做的事情是销毁请求执行过程中的一些内存使用
- 调用 register_shutdown_function 注册的函数
- 调用 __destruction 函数
- flush 输出缓存
- 调用各扩展的 RSHUTDOWN 函数
- 关闭 php 输出
- 销毁超全局数组
- 释放扫描器, 执行器, 编译器, ini_entries
- 调用各扩展的 post_deactivate_func 函数
- 关闭 sapi
- 关闭内存管理器
浙公网安备 33010602011771号