Starting Up and Shutting Down

Table of contents:

This startup and shutdown process happens in two separate startup phases and two separate shutdown phases. One cycle is for the PHP interpreter as a whole to perform an initial setup of structures and values that will persist for the life of the SAPI. The second is for transient settings that only last as long as a single page request.

During the initial startup, before any request has been made, PHP calls every extension's MINIT (Module Initialization) method. Here, extensions are expected to declare constants, define classes, and register resource, stream, and filter handlers that all future script requests will use. Features such as these, which are designed to exist across all requests, are referred to as being persistent.

A common MINIT method might look like the following:

/* Initialize the myextension module
 * This will happen immediately upon SAPI startup
 /* Globals: Chapter 12 */

#ifdef ZTS
 (ts_allocate_ctor) myextension_globals_ctor,
 (ts_allocate_dtor) myextension_globals_dtor);
 myextension_globals_ctor(&myextension_globals TSRMLS_CC);

 /* REGISTER_INI_ENTRIES() refers to a global
 * structure that will be covered in
 * Chapter 13 "INI Settings"

 /* define('MYEXT_MEANING', 42); */
 /* define('MYEXT_FOO', 'bar'); */

 /* Resources: chapter 9 */
 le_myresource = zend_register_list_destructors_ex(
 php_myext_myresource_dtor, NULL,
 "My Resource Type", module_number);
 le_myresource_persist = zend_register_list_destructors_ex(
 NULL, php_myext_myresource_dtor,
 "My Resource Type", module_number);

 /* Stream Filters: Chapter 16 */
 if (FAILURE == php_stream_filter_register_factory("myfilter",
 &php_myextension_filter_factory TSRMLS_CC)) {
 return FAILURE;

 /* Stream Wrappers: Chapter 15 */
 if (FAILURE == php_register_url_stream_wrapper ("myproto",
 &php_myextension_stream_wrapper TSRMLS_CC)) {
 return FAILURE;

 /* Autoglobals: Chapter 12 */
#ifdef ZEND_ENGINE_2
 if (zend_register_auto_global("_MYEXTENSION", sizeof("_MYEXTENSION") - 1,
 return FAILURE;
 zend_auto_global_disable_jit ("_MYEXTENSION", sizeof("_MYEXTENSION") - 1
 if (zend_register_auto_global("_MYEXTENSION", sizeof("_MYEXTENSION") - 1
 return FAILURE;
 return SUCCESS;

After a request has been made, PHP sets up an operating environment including a symbol table (where variables are stored) and synchronizes per-directory configuration values. PHP then loops through its extensions again, this time calling each one's RINIT (Request Initialization) method. Here, an extension may reset global variables to default values, prepopulate variables into the script's symbol table, or perform other tasks such as logging the page request to a file. RINIT can be thought of as a kind of auto_prepend_file directive for all scripts requested.

An RINIT method might be expected to look like this:

/* Run at the start of every page request
 zval *myext_autoglobal;

 /* Initialize the autoglobal variable
 * declared in the MINIT function
 * as an empty array.
 * This is equivalent to performing:
 * $_MYEXTENSION = array();
 zend_hash_add(&EG(symbol_table), "_MYEXTENSION", sizeof("_MYEXTENSION") - 1,
 (void**)&myext_autoglobal, sizeof(zval*), NULL);

 return SUCCESS;

After a request has completed processing, either by reaching the end of the script file or by exiting through a die() or exit() statement, PHP starts the cleanup process by calling each extension's RSHUTDOWN (Request Shutdown) method. RSHUTDOWN corresponds to auto_append_file in much the same was as RINIT corresponds to auto_prepend_file. The most important difference between RSHUTDOWN and auto_append_file, however, is that RSHUTDOWN will always be executed, whereas a call to die() or exit() inside the userspace script will skip any auto_append_file.

Any last minute tasks that need to be performed can be handled in RSHUTDOWN before the symbol table and other resources are destroyed. After all RSHUTDOWN methods have completed, every variable in the symbol table is implicitly unset(), during which all non-persistent resource and object destructors are called in order to free resources gracefully.

/* Run at the end of every page request
 zval **myext_autoglobal;

 if (zend_hash_find(&EG(symbol_table), "_MYEXTENSION", sizeof("_MYEXTENSION"),
 (void**)&myext_autoglobal) == SUCCESS) {
 /* Do something meaningful
 * with the values of the
 * $_MYEXTENSION array
 php_myextension_handle_values(myext_autoglobal TSRMLS_CC);
 return SUCCESS;

Finally, when all requests have been fulfilled and the web server or other SAPI is ready to shut down, PHP loops through each extension's MSHUTDOWN (Module Shutdown) method. This is an extension's last chance to unregister handlers and free persistent memory allocated during the MINIT cycle.

/* This module is being unloaded
 * constants and functions will be
 * automatically purged,
 * persistent resources, class entries,
 * and stream handlers must be
 * manually unregistered.
 php_unregister_url_stream_wrapper ("myproto" TSRMLS_CC);
 php_stream_filter_unregister_factory ("myfilter" TSRMLS_CC);
 return SUCCESS;

Life Cycles

The PHP Life Cycle

Variables from the Inside Out

Memory Management

Setting Up a Build Environment

Your First Extension

Returning Values

Accepting Parameters

Working with Arrays and HashTables

The Resource Data Type

PHP4 Objects

PHP5 Objects

Startup, Shutdown, and a Few Points in Between

INI Settings

Accessing Streams

Implementing Streams

Diverting the Stream

Configuration and Linking

Extension Generators

Setting Up a Host Environment

Advanced Embedding

Appendix A. A Zend API Reference

Appendix B. PHPAPI

Appendix C. Extending and Embedding Cookbook

Appendix D. Additional Resources

Extending and Embedding PHP
Extending and Embedding PHP
ISBN: 067232704X
EAN: 2147483647
Year: 2007
Pages: 175
Authors: Sara Golemon © 2008-2020.
If you may any questions please contact us: