source: trunk/xcache.c @ 1061

Last change on this file since 1061 was 1061, checked in by moo, 21 months ago

fix compatibility workarround

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