Cycles

In addition to these four methods, which are linked directly into the module entry structure, there are two more methods used only in threaded environments that handle the startup and shutdown of individual threads and the private storage space they use. To get started, set up a slightly more comprehensive version of the basic extension skeleton using these source files in ext/sample4 under your PHP source tree (see Listings 12.1 through 12.3):

Listing 12.1. config.m4

PHP_ARG_ENABLE(sample4,
 [Whether to enable the "sample4" extension],
 [ enable-sample4 Enable "sample4" extension support])

if test $PHP_SAMPLE4 != "no"; then
 PHP_SUBST(SAMPLE4_SHARED_LIBADD)
 PHP_NEW_EXTENSION(sample4, sample4.c, $ext_shared)
fi

Listing 12.2. php_sample4.h

#ifndef PHP_SAMPLE4_H
/* Prevent double inclusion */
#define PHP_SAMPLE4_H

/* Define Extension Properties */
#define PHP_SAMPLE4_EXTNAME "sample4"
#define PHP_SAMPLE4_EXTVER "1.0"

/* Import configure options
 when building outside of
 the PHP source tree */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/* Include PHP Standard Header */
#include "php.h"

/* Define the entry point symbol
 * Zend will use when loading this module
 */
extern zend_module_entry sample4_module_entry;
#define phpext_sample4_ptr &sample4_module_entry

#endif /* PHP_SAMPLE4_H */

Listing 12.3. sample4.c

#include "php_sample4.h"
#include "ext/standard/info.h"

static function_entry php_sample4_functions[] = {
 { NULL, NULL, NULL }
};

PHP_MINIT_FUNCTION(sample4)
{
 return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(sample4)
{
 return SUCCESS;
}

PHP_RINIT_FUNCTION(sample4)
{
 return SUCCESS;
}

PHP_RSHUTDOWN_FUNCTION(sample4)
{
 return SUCCESS;
}
PHP_MINFO_FUNCTION(sample4)
{
}

zend_module_entry sample4_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
 STANDARD_MODULE_HEADER,
#endif
 PHP_SAMPLE4_EXTNAME,
 php_sample4_functions,
 PHP_MINIT(sample4),
 PHP_MSHUTDOWN(sample4),
 PHP_RINIT(sample4),
 PHP_RSHUTDOWN(sample4),
 PHP_MINFO(sample4),
#if ZEND_MODULE_API_NO >= 20010901
 PHP_SAMPLE4_EXTVER,
#endif
 STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_SAMPLE4
ZEND_GET_MODULE(sample4)
#endif

Notice that each startup and shutdown method returns SUCCESS on exit. If any method were to return FAILURE, the module load or request would be aborted by PHP to avoid any serious problems elsewhere in the engine.

Module Cycle

MINIT should be familiar as you've used it several times throughout the previous chapters. It's triggered the first time a module is loaded into a process space, which for single-request SAPIs such as CLI And CGI, or multithreaded SAPIs such as Apache2-worker, is exactly once because no forking is involved.

For multiprocess SAPIs such as Apache1 and Apache2-prefork, multiple web server processes are forked and with them multiple instances of mod_php. Each instance of mod_php must then load its own instance of your extension module meaning that your MINIT method is run multiple times, but still only once per process space.

When a module is unloaded, the MSHUTDOWN method is invoked so that any resources owned by that module, such as persistent memory blocks, may be freed and returned to the operating system.

Enginewide features, such as Class Entries, Resource IDs, Stream wrappers and filters, userspace autoglobals, and php.ini entries are some common examples of resources that get allocated and cleaned up in the Module INIT and SHUTDOWN phases respectively.

Note

In theory, you could skip proper resource cleanup during the MSHUTDOWN phase, opting instead to allow the OS to implicitly free memory and file handles. When using your extension with Apache 1.3 however, you'll discover an interesting quirk as Apache will load mod_php, launching all MINIT methods in the process, and then immediately unload mod_php, TRigging the MSHUTDOWN methods, and then load it again. Without a proper MSHUTDOWN phase, resources allocated during the initial MINIT will be leaked and wasted.

 

Thread Cycle

In multithreaded SAPIs, it's sometimes necessary for each thread to allocate its own independent resources or track its own personal per-request counters. For these special situations there is a per-thread hook that allows for an additional set of startup and shutdown methods to be executed. Typically when a multithreaded SAPI such as Apache2-worker starts up, it will spin a dozen or more threads in order to be able to handle multiple concurrent requests.

Any resources that may be shared between requests, but must not be accessed by multiple threads in the same process space simultaneously, are usually allocated and freed in the thread constructor and destructor methods. Examples might include persistent resources in the EG(persistent_list) HashTable because they often include network or file resources that make assumptions about the consistency of their state from instruction to instruction.

Request Cycle

The last and most transient startup and shutdown cycle occurs with every request, and is where your extension might choose to initialize default userspace variables or initialize internal state tracking information. Because both of these methods are called on every single page request, it's important to keep the processing and memory allocation load to a bare minimum.


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

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net