source: trunk/xcache.c @ 1047

Last change on this file since 1047 was 1047, checked in by moo, 2 years ago

refactor: fall back to more simpler trick

  • Property svn:eol-style set to native
File size: 21.2 KB
Line 
1/* {{{ macros */
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5
6#include <signal.h>
7
8#include "xcache.h"
9
10#ifdef HAVE_XCACHE_OPTIMIZER
11#   include "mod_optimizer/xc_optimizer.h"
12#endif
13#ifdef HAVE_XCACHE_CACHER
14#   include "mod_cacher/xc_cacher.h"
15#endif
16#ifdef HAVE_XCACHE_COVERAGER
17#   include "mod_coverager/xc_coverager.h"
18#endif
19#ifdef HAVE_XCACHE_DISASSEMBLER
20#   include "mod_disassembler/xc_disassembler.h"
21#endif
22
23#include "xcache_globals.h"
24#include "xcache/xc_extension.h"
25#include "xcache/xc_ini.h"
26#include "xcache/xc_const_string.h"
27#include "xcache/xc_opcode_spec.h"
28#include "xcache/xc_utils.h"
29#include "util/xc_stack.h"
30
31#include "php.h"
32#include "ext/standard/info.h"
33#include "ext/standard/php_string.h"
34/* }}} */
35
36/* {{{ globals */
37static char *xc_coredump_dir = NULL;
38static zend_bool xc_disable_on_crash = 0;
39
40static zend_compile_file_t *old_compile_file = NULL;
41
42zend_bool xc_test = 0;
43
44ZEND_DECLARE_MODULE_GLOBALS(xcache)
45
46/* }}} */
47
48static zend_op_array *xc_check_initial_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
49{
50    XG(initial_compile_file_called) = 1;
51    return old_compile_file(h, type TSRMLS_CC);
52}
53/* }}} */
54
55/* module helper function */
56static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */
57{
58    typedef struct {
59        const char *prefix;
60        zend_uchar (*getsize)();
61        const char *(*get)(zend_uchar i);
62    } xc_meminfo_t;
63    xc_meminfo_t nameinfos[] = {
64        { "",        xc_get_op_type_count,   xc_get_op_type   },
65        { "",        xc_get_data_type_count, xc_get_data_type },
66        { "",        xc_get_opcode_count,    xc_get_opcode    },
67        { "OPSPEC_", xc_get_op_spec_count,   xc_get_op_spec   },
68        { NULL, NULL, NULL }
69    };
70    xc_meminfo_t* p;
71    zend_uchar i, count;
72    char const_name[96];
73    int const_name_len;
74    int undefdone = 0;
75
76    for (p = nameinfos; p->getsize; p ++) {
77        count = p->getsize();
78        for (i = 0; i < count; i ++) {
79            const char *name = p->get(i);
80            if (!name) continue;
81            if (strcmp(name, "UNDEF") == 0) {
82                if (undefdone) continue;
83                undefdone = 1;
84            }
85            const_name_len = snprintf(const_name, sizeof(const_name), "XC_%s%s", p->prefix, name);
86            zend_register_long_constant(const_name, const_name_len+1, i, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
87        }
88    }
89
90    zend_register_long_constant(ZEND_STRS("XC_SIZEOF_TEMP_VARIABLE"), sizeof(temp_variable), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
91    zend_register_stringl_constant(ZEND_STRS("XCACHE_VERSION"), ZEND_STRL(XCACHE_VERSION), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
92    zend_register_stringl_constant(ZEND_STRS("XCACHE_MODULES"), ZEND_STRL(XCACHE_MODULES), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
93    return 0;
94}
95/* }}} */
96/* {{{ PHP_GINIT_FUNCTION(xcache) */
97static
98#ifdef PHP_GINIT_FUNCTION
99PHP_GINIT_FUNCTION(xcache)
100#else
101void xc_init_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
102#endif
103{
104    memset(xcache_globals, 0, sizeof(zend_xcache_globals));
105
106#ifdef HAVE_XCACHE_CONSTANT
107    zend_hash_init_ex(&xcache_globals->internal_constant_table, 1, NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0);
108#endif
109    zend_hash_init_ex(&xcache_globals->internal_function_table, 1, NULL, NULL, 1, 0);
110    zend_hash_init_ex(&xcache_globals->internal_class_table,    1, NULL, NULL, 1, 0);
111}
112/* }}} */
113/* {{{ PHP_GSHUTDOWN_FUNCTION(xcache) */
114static
115#ifdef PHP_GSHUTDOWN_FUNCTION
116PHP_GSHUTDOWN_FUNCTION(xcache)
117#else
118void xc_shutdown_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
119#endif
120{
121    size_t i;
122
123    if (xcache_globals->php_holds != NULL) {
124        for (i = 0; i < xcache_globals->php_holds_size; i ++) {
125            xc_stack_destroy(&xcache_globals->php_holds[i]);
126        }
127        free(xcache_globals->php_holds);
128        xcache_globals->php_holds = NULL;
129        xcache_globals->php_holds_size = 0;
130    }
131
132    if (xcache_globals->var_holds != NULL) {
133        for (i = 0; i < xcache_globals->var_holds_size; i ++) {
134            xc_stack_destroy(&xcache_globals->var_holds[i]);
135        }
136        free(xcache_globals->var_holds);
137        xcache_globals->var_holds = NULL;
138        xcache_globals->var_holds_size = 0;
139    }
140
141    if (xcache_globals->internal_table_copied) {
142#ifdef HAVE_XCACHE_CONSTANT
143        zend_hash_destroy(&xcache_globals->internal_constant_table);
144#endif
145        zend_hash_destroy(&xcache_globals->internal_function_table);
146        zend_hash_destroy(&xcache_globals->internal_class_table);
147    }
148}
149/* }}} */
150
151/* {{{ proto int xcache_get_refcount(mixed variable)
152   XCache internal uses only: Get reference count of variable */
153PHP_FUNCTION(xcache_get_refcount)
154{
155    zval *variable;
156    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) {
157        RETURN_NULL();
158    }
159
160    RETURN_LONG(Z_REFCOUNT(*variable));
161}
162/* }}} */
163/* {{{ proto bool xcache_get_isref(mixed variable)
164   XCache internal uses only: Check if variable data is marked referenced */
165#ifdef ZEND_BEGIN_ARG_INFO_EX
166ZEND_BEGIN_ARG_INFO_EX(arginfo_xcache_get_isref, 0, 0, 1)
167    ZEND_ARG_INFO(1, variable)
168ZEND_END_ARG_INFO()
169#else
170static unsigned char arginfo_xcache_get_isref[] = { 1, BYREF_FORCE };
171#endif
172
173PHP_FUNCTION(xcache_get_isref)
174{
175    zval *variable;
176    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) {
177        RETURN_NULL();
178    }
179
180    RETURN_BOOL(Z_ISREF(*variable) && Z_REFCOUNT(*variable) >= 3);
181}
182/* }}} */
183#ifdef HAVE_XCACHE_DPRINT
184/* {{{ proto bool  xcache_dprint(mixed value)
185   Prints variable (or value) internal struct (debug only) */
186PHP_FUNCTION(xcache_dprint)
187{
188    zval *value;
189
190    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
191        return;
192    }
193    xc_dprint_zval(value, 0 TSRMLS_CC);
194}
195/* }}} */
196#endif
197/* {{{ proto string xcache_asm(string filename)
198 */
199#ifdef HAVE_XCACHE_ASSEMBLER
200PHP_FUNCTION(xcache_asm)
201{
202}
203#endif
204/* }}} */
205/* {{{ proto string xcache_encode(string filename)
206   Encode php file into XCache opcode encoded format */
207#ifdef HAVE_XCACHE_ENCODER
208PHP_FUNCTION(xcache_encode)
209{
210}
211#endif
212/* }}} */
213/* {{{ proto bool xcache_decode_file(string filename)
214   Decode(load) opcode from XCache encoded format file */
215#ifdef HAVE_XCACHE_DECODER
216PHP_FUNCTION(xcache_decode_file)
217{
218}
219#endif
220/* }}} */
221/* {{{ proto bool xcache_decode_string(string data)
222   Decode(load) opcode from XCache encoded format data */
223#ifdef HAVE_XCACHE_DECODER
224PHP_FUNCTION(xcache_decode_string)
225{
226}
227#endif
228/* }}} */
229/* {{{ xc_call_getter */
230typedef const char *(xc_name_getter_t)(zend_uchar type);
231static void xc_call_getter(xc_name_getter_t getter, int count, INTERNAL_FUNCTION_PARAMETERS)
232{
233    long spec;
234    const char *name;
235
236    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
237        return;
238    }
239    if (spec >= 0 && spec < count) {
240        name = getter((zend_uchar) spec);
241        if (name) {
242            /* RETURN_STRING */
243            int len = strlen(name);
244            return_value->value.str.len = len;
245            return_value->value.str.val = estrndup(name, len);
246            return_value->type = IS_STRING; 
247            return;
248        }
249    }
250    RETURN_NULL();
251}
252/* }}} */
253/* {{{ proto string xcache_get_op_type(int op_type) */
254PHP_FUNCTION(xcache_get_op_type)
255{
256    xc_call_getter(xc_get_op_type, xc_get_op_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
257}
258/* }}} */
259/* {{{ proto string xcache_get_data_type(int type) */
260PHP_FUNCTION(xcache_get_data_type)
261{
262    xc_call_getter(xc_get_data_type, xc_get_data_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
263}
264/* }}} */
265/* {{{ proto string xcache_get_opcode(int opcode) */
266PHP_FUNCTION(xcache_get_opcode)
267{
268    xc_call_getter(xc_get_opcode, xc_get_opcode_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
269}
270/* }}} */
271/* {{{ proto string xcache_get_op_spec(int op_type) */
272PHP_FUNCTION(xcache_get_op_spec)
273{
274    xc_call_getter(xc_get_op_spec, xc_get_op_spec_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
275}
276/* }}} */
277/* {{{ proto string xcache_get_opcode_spec(int opcode) */
278PHP_FUNCTION(xcache_get_opcode_spec)
279{
280    long spec;
281    const xc_opcode_spec_t *opspec;
282
283    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
284        return;
285    }
286    if ((zend_uchar) spec <= xc_get_opcode_spec_count()) {
287        opspec = xc_get_opcode_spec((zend_uchar) spec);
288        if (opspec) {
289            array_init(return_value);
290            add_assoc_long_ex(return_value, ZEND_STRS("ext"), opspec->ext);
291            add_assoc_long_ex(return_value, ZEND_STRS("op1"), opspec->op1);
292            add_assoc_long_ex(return_value, ZEND_STRS("op2"), opspec->op2);
293            add_assoc_long_ex(return_value, ZEND_STRS("res"), opspec->res);
294            return;
295        }
296    }
297    RETURN_NULL();
298}
299/* }}} */
300/* {{{ proto mixed xcache_get_special_value(zval value)
301   XCache internal use only: For decompiler to get static value with type fixed */
302PHP_FUNCTION(xcache_get_special_value)
303{
304    zval *value;
305
306    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
307        return;
308    }
309
310    switch ((Z_TYPE_P(value) & IS_CONSTANT_TYPE_MASK)) {
311    case IS_CONSTANT:
312        *return_value = *value;
313        zval_copy_ctor(return_value);
314        return_value->type = UNISW(IS_STRING, UG(unicode) ? IS_UNICODE : IS_STRING);
315        break;
316
317    case IS_CONSTANT_ARRAY:
318        *return_value = *value;
319        zval_copy_ctor(return_value);
320        return_value->type = IS_ARRAY;
321        break;
322
323    default:
324        RETURN_NULL();
325    }
326}
327/* }}} */
328/* {{{ proto int xcache_get_type(zval value)
329   XCache internal use only for disassembler to get variable type in engine level */
330PHP_FUNCTION(xcache_get_type)
331{
332    zval *value;
333
334    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
335        return;
336    }
337
338    RETURN_LONG(Z_TYPE_P(value));
339}
340/* }}} */
341/* {{{ proto string xcache_coredump(int op_type) */
342PHP_FUNCTION(xcache_coredump)
343{
344    if (xc_test) {
345        raise(SIGSEGV);
346    }
347    else {
348        php_error_docref(NULL TSRMLS_CC, E_WARNING, "xcache.test must be enabled to test xcache_coredump()");
349    }
350}
351/* }}} */
352/* {{{ proto string xcache_is_autoglobal(string name) */
353PHP_FUNCTION(xcache_is_autoglobal)
354{
355    zval *name;
356
357    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
358        return;
359    }
360
361#ifdef IS_UNICODE
362    convert_to_unicode(name);
363#else
364    convert_to_string(name);
365#endif
366
367    RETURN_BOOL(zend_u_hash_exists(CG(auto_globals), UG(unicode), Z_STRVAL_P(name), Z_STRLEN_P(name) + 1));
368}
369/* }}} */
370static zend_function_entry xcache_functions[] = /* {{{ */
371{
372    PHP_FE(xcache_coredump,          NULL)
373#ifdef HAVE_XCACHE_ASSEMBLER
374    PHP_FE(xcache_asm,               NULL)
375#endif
376#ifdef HAVE_XCACHE_ENCODER
377    PHP_FE(xcache_encode,            NULL)
378#endif
379#ifdef HAVE_XCACHE_DECODER
380    PHP_FE(xcache_decode_file,       NULL)
381    PHP_FE(xcache_decode_string,     NULL)
382#endif
383    PHP_FE(xcache_get_special_value, NULL)
384    PHP_FE(xcache_get_type,          NULL)
385    PHP_FE(xcache_get_op_type,       NULL)
386    PHP_FE(xcache_get_data_type,     NULL)
387    PHP_FE(xcache_get_opcode,        NULL)
388    PHP_FE(xcache_get_opcode_spec,   NULL)
389    PHP_FE(xcache_is_autoglobal,     NULL)
390    PHP_FE(xcache_get_refcount,      NULL)
391    PHP_FE(xcache_get_isref,         arginfo_xcache_get_isref)
392#ifdef HAVE_XCACHE_DPRINT
393    PHP_FE(xcache_dprint,            NULL)
394#endif
395    PHP_FE_END
396};
397/* }}} */
398
399#ifdef ZEND_WIN32
400#include "dbghelp.h"
401typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
402        CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
403        CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
404        CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
405        );
406
407static PTOP_LEVEL_EXCEPTION_FILTER oldFilter = NULL;
408static HMODULE dbghelpModule = NULL;
409static char crash_dumpPath[_MAX_PATH] = { 0 };
410static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump = NULL;
411
412static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */
413{
414    HANDLE fileHandle;
415
416    SetUnhandledExceptionFilter(oldFilter);
417
418    /* create the file */
419    fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
420
421    if (fileHandle != INVALID_HANDLE_VALUE) {
422        MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
423        BOOL ok;
424
425        exceptionInformation.ThreadId = GetCurrentThreadId();
426        exceptionInformation.ExceptionPointers = pExceptionInfo;
427        exceptionInformation.ClientPointers = FALSE;
428
429        /* write the dump */
430        ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal|MiniDumpWithDataSegs|MiniDumpWithIndirectlyReferencedMemory, &exceptionInformation, NULL, NULL);
431        CloseHandle(fileHandle);
432        if (ok) {
433            zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath);
434            return EXCEPTION_EXECUTE_HANDLER;
435        }
436        else {
437            zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError());
438        }
439    }
440    else {
441        zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError());
442    }
443
444    return EXCEPTION_CONTINUE_SEARCH;
445}
446/* }}} */
447
448static void xcache_restore_crash_handler() /* {{{ */
449{
450    if (oldFilter) {
451        SetUnhandledExceptionFilter(oldFilter);
452        oldFilter = NULL;
453    }
454}
455/* }}} */
456static void xcache_init_crash_handler() /* {{{ */
457{
458    /* firstly see if dbghelp.dll is around and has the function we need
459       look next to the EXE first, as the one in System32 might be old
460       (e.g. Windows 2000) */
461    char dbghelpPath[_MAX_PATH];
462
463    if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) {
464        char *slash = strchr(dbghelpPath, '\\');
465        if (slash) {
466            strcpy(slash + 1, "DBGHELP.DLL");
467            dbghelpModule = LoadLibrary(dbghelpPath);
468        }
469    }
470
471    if (!dbghelpModule) {
472        /* load any version we can */
473        dbghelpModule = LoadLibrary("DBGHELP.DLL");
474        if (!dbghelpModule) {
475            zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found");
476            return;
477        }
478    }
479
480    dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump");
481    if (!dbghelp_MiniDumpWriteDump) {
482        zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old. Get updated dll and put it aside of php_xcache.dll");
483        return;
484    }
485
486#ifdef XCACHE_VERSION_REVISION
487#define REVISION "r" XCACHE_VERSION_REVISION
488#else
489#define REVISION ""
490#endif
491    sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s%s-%lu-%lu.dmp", xc_coredump_dir, zend_get_module_version("standard"), XCACHE_VERSION, REVISION, (unsigned long) time(NULL), (unsigned long) GetCurrentProcessId());
492#undef REVISION
493
494    oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter);
495}
496/* }}} */
497#else
498/* old signal handlers {{{ */
499typedef void (*xc_sighandler_t)(int);
500#define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL
501#include "util/xc_foreachcoresig.h"
502#undef FOREACH_SIG
503/* }}} */
504static void xcache_signal_handler(int sig);
505static void xcache_restore_crash_handler() /* {{{ */
506{
507#define FOREACH_SIG(sig) do { \
508    if (old_##sig##_handler != xcache_signal_handler) { \
509        signal(sig, old_##sig##_handler); \
510    } \
511    else { \
512        signal(sig, SIG_DFL); \
513    } \
514} while (0)
515#include "util/xc_foreachcoresig.h"
516#undef FOREACH_SIG
517}
518/* }}} */
519static void xcache_init_crash_handler() /* {{{ */
520{
521#define FOREACH_SIG(sig) \
522    old_##sig##_handler = signal(sig, xcache_signal_handler)
523#include "util/xc_foreachcoresig.h"
524#undef FOREACH_SIG
525}
526/* }}} */
527static void xcache_signal_handler(int sig) /* {{{ */
528{
529    xcache_restore_crash_handler();
530    if (xc_coredump_dir && xc_coredump_dir[0]) {
531        if (chdir(xc_coredump_dir) != 0) {
532            /* error, but nothing can do about it
533             * and should'nt print anything which might SEGV again */
534        }
535    }
536    if (xc_disable_on_crash) {
537        xc_disable_on_crash = 0;
538        xc_cacher_disable();
539    }
540    raise(sig);
541}
542/* }}} */
543#endif
544
545/* {{{ incompatible zend extensions handling */
546typedef struct {
547    const char *name;
548    startup_func_t old_startup;
549} xc_incompatible_zend_extension_info_t;
550static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = {
551    { "Zend Optimizer", NULL }
552};
553
554static xc_incompatible_zend_extension_info_t *xc_get_incompatible_zend_extension_info(const char *name)
555{
556    size_t i;
557
558    for (i = 0; i < sizeof(xc_incompatible_zend_extensions) / sizeof(xc_incompatible_zend_extensions[0]); ++i) {
559        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = &xc_incompatible_zend_extensions[i];
560        if (strcmp(incompatible_zend_extension_info->name, name) == 0) {
561            return incompatible_zend_extension_info;
562        }
563    }
564
565    return NULL;
566}
567/* }}} */
568static int xc_incompatible_zend_extension_startup_hook(zend_extension *extension) /* {{{ */
569{
570    xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
571    int status;
572    zend_bool catched = 0;
573    zend_llist old_zend_extensions = zend_extensions;
574    TSRMLS_FETCH();
575
576    /* hide all extensions from it */
577    zend_extensions.head = NULL;
578    zend_extensions.count = 0;
579
580    /* restore */
581    extension->startup = incompatible_zend_extension_info->old_startup;
582    incompatible_zend_extension_info->old_startup = NULL;
583    assert(extension->startup);
584
585    zend_try {
586        status = extension->startup(extension);
587    } zend_catch {
588        catched = 1;
589    } zend_end_try();
590
591    zend_extensions = old_zend_extensions;
592    if (catched) {
593        zend_bailout();
594    }
595    return status;
596}
597/* }}} */
598static int xc_zend_startup(zend_extension *extension) /* {{{ */
599{
600    zend_llist_position lpos;
601    zend_extension *ext;
602
603    ext = (zend_extension *) zend_extensions.head->data;
604    if (strcmp(ext->name, XCACHE_NAME) != 0) {
605        zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name);
606    }
607
608    old_compile_file = zend_compile_file;
609    zend_compile_file = xc_check_initial_compile_file;
610
611    for (ext = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &lpos);
612            ext;
613            ext = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &lpos)) {
614        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
615        if (incompatible_zend_extension_info) {
616            assert(!incompatible_zend_extension_info->old_startup);
617            incompatible_zend_extension_info->old_startup = ext->startup;
618            ext->startup = xc_incompatible_zend_extension_startup_hook;
619        }
620    }
621    return SUCCESS;
622}
623/* }}} */
624static void xc_zend_shutdown(zend_extension *extension) /* {{{ */
625{
626}
627/* }}} */
628/* {{{ zend extension definition structure */
629static zend_extension xc_zend_extension_entry = {
630    XCACHE_NAME,
631    XCACHE_VERSION,
632    XCACHE_AUTHOR,
633    XCACHE_URL,
634    XCACHE_COPYRIGHT,
635    xc_zend_startup,
636    xc_zend_shutdown,
637    NULL,           /* activate_func_t */
638    NULL,           /* deactivate_func_t */
639    NULL,           /* message_handler_func_t */
640    NULL,           /* op_array_handler_func_t */
641    NULL,           /* statement_handler_func_t */
642    NULL,           /* fcall_begin_handler_func_t */
643    NULL,           /* fcall_end_handler_func_t */
644    NULL,           /* op_array_ctor_func_t */
645    NULL,           /* op_array_dtor_func_t */
646    STANDARD_ZEND_EXTENSION_PROPERTIES
647};
648/* }}} */
649
650/* {{{ PHP_INI */
651PHP_INI_BEGIN()
652    PHP_INI_ENTRY1     ("xcache.coredump_directory",      "", PHP_INI_SYSTEM, xcache_OnUpdateString,   &xc_coredump_dir)
653    PHP_INI_ENTRY1     ("xcache.disable_on_crash",       "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_disable_on_crash)
654    PHP_INI_ENTRY1     ("xcache.test",                   "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_test)
655    STD_PHP_INI_BOOLEAN("xcache.experimental",           "0", PHP_INI_ALL,    OnUpdateBool,        experimental,      zend_xcache_globals, xcache_globals)
656PHP_INI_END()
657/* }}} */
658static PHP_MINFO_FUNCTION(xcache) /* {{{ */
659{
660    php_info_print_table_start();
661    php_info_print_table_row(2, "XCache Version", XCACHE_VERSION);
662#ifdef XCACHE_VERSION_REVISION
663    php_info_print_table_row(2, "Revision", "r" XCACHE_VERSION_REVISION);
664#endif
665    php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
666    php_info_print_table_end();
667
668    DISPLAY_INI_ENTRIES();
669}
670/* }}} */
671static PHP_MINIT_FUNCTION(xcache) /* {{{ */
672{
673#ifndef PHP_GINIT
674    ZEND_INIT_MODULE_GLOBALS(xcache, xc_init_globals, xc_shutdown_globals);
675#endif
676    REGISTER_INI_ENTRIES();
677
678    if (xc_coredump_dir && xc_coredump_dir[0]) {
679        xcache_init_crash_handler();
680    }
681
682    xc_init_constant(module_number TSRMLS_CC);
683    xc_shm_init_modules();
684
685    /* must be the first */
686    xcache_zend_extension_add(&xc_zend_extension_entry, 1);
687#ifdef HAVE_XCACHE_OPTIMIZER
688    xc_optimizer_startup_module();
689#endif
690#ifdef HAVE_XCACHE_CACHER
691    xc_cacher_startup_module();
692#endif
693#ifdef HAVE_XCACHE_COVERAGER
694    xc_coverager_startup_module();
695#endif
696#ifdef HAVE_XCACHE_DISASSEMBLER
697    xc_disassembler_startup_module();
698#endif
699
700    return SUCCESS;
701
702err_init:
703    return FAILURE;
704}
705/* }}} */
706static PHP_MSHUTDOWN_FUNCTION(xcache) /* {{{ */
707{
708    if (old_compile_file && zend_compile_file == xc_check_initial_compile_file) {
709        zend_compile_file = old_compile_file;
710        old_compile_file = NULL;
711    }
712
713    if (xc_coredump_dir && xc_coredump_dir[0]) {
714        xcache_restore_crash_handler();
715    }
716    if (xc_coredump_dir) {
717        pefree(xc_coredump_dir, 1);
718        xc_coredump_dir = NULL;
719    }
720#ifndef PHP_GINIT
721#   ifdef ZTS
722    ts_free_id(xcache_globals_id);
723#   else
724    xc_shutdown_globals(&xcache_globals TSRMLS_CC);
725#   endif
726#endif
727
728    UNREGISTER_INI_ENTRIES();
729    xcache_zend_extension_remove(&xc_zend_extension_entry);
730    return SUCCESS;
731}
732/* }}} */
733/* {{{ module dependencies */
734#ifdef STANDARD_MODULE_HEADER_EX
735static zend_module_dep xcache_module_deps[] = {
736    ZEND_MOD_REQUIRED("standard")
737    ZEND_MOD_CONFLICTS("apc")
738    ZEND_MOD_CONFLICTS("eAccelerator")
739    ZEND_MOD_CONFLICTS("Turck MMCache")
740    ZEND_MOD_END
741};
742#endif
743/* }}} */ 
744/* {{{ module definition structure */
745zend_module_entry xcache_module_entry = {
746#ifdef STANDARD_MODULE_HEADER_EX
747    STANDARD_MODULE_HEADER_EX,
748    NULL,
749    xcache_module_deps,
750#else
751    STANDARD_MODULE_HEADER,
752#endif
753    XCACHE_NAME,
754    xcache_functions,
755    PHP_MINIT(xcache),
756    PHP_MSHUTDOWN(xcache),
757    NULL, /* RINIT */
758    NULL, /* RSHUTDOWN */
759    PHP_MINFO(xcache),
760    XCACHE_VERSION,
761#ifdef PHP_GINIT
762    PHP_MODULE_GLOBALS(xcache),
763    PHP_GINIT(xcache),
764    PHP_GSHUTDOWN(xcache),
765#endif
766#ifdef ZEND_ENGINE_2
767    NULL /* ZEND_MODULE_POST_ZEND_DEACTIVATE_N */,
768#else
769    NULL,
770    NULL,
771#endif
772    STANDARD_MODULE_PROPERTIES_EX
773};
774
775#ifdef COMPILE_DL_XCACHE
776ZEND_GET_MODULE(xcache)
777#endif
778/* }}} */
Note: See TracBrowser for help on using the repository browser.