source: trunk/xcache.c @ 1131

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

refactor: fix build for previous code clean up

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