source: trunk/xcache.c @ 1106

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

adds disable_on_crash support for win32

  • Property svn:eol-style set to native
File size: 21.5 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    LONG ret = EXCEPTION_CONTINUE_SEARCH;
420
421    SetUnhandledExceptionFilter(oldFilter);
422
423    /* create the file */
424    fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
425
426    if (fileHandle != INVALID_HANDLE_VALUE) {
427        MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
428        BOOL ok;
429
430        exceptionInformation.ThreadId = GetCurrentThreadId();
431        exceptionInformation.ExceptionPointers = pExceptionInfo;
432        exceptionInformation.ClientPointers = FALSE;
433
434        /* write the dump */
435        ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal|MiniDumpWithDataSegs|MiniDumpWithIndirectlyReferencedMemory, &exceptionInformation, NULL, NULL);
436        CloseHandle(fileHandle);
437        if (ok) {
438            zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath);
439            ret = EXCEPTION_EXECUTE_HANDLER;
440        }
441        else {
442            zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError());
443        }
444    }
445    else {
446        zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError());
447    }
448
449    if (xc_disable_on_crash) {
450        xc_disable_on_crash = 0;
451        xc_cacher_disable();
452    }
453
454    return ret;
455}
456/* }}} */
457
458static void xcache_restore_crash_handler() /* {{{ */
459{
460    if (oldFilter) {
461        SetUnhandledExceptionFilter(oldFilter);
462        oldFilter = NULL;
463    }
464}
465/* }}} */
466static void xcache_init_crash_handler() /* {{{ */
467{
468    /* firstly see if dbghelp.dll is around and has the function we need
469       look next to the EXE first, as the one in System32 might be old
470       (e.g. Windows 2000) */
471    char dbghelpPath[_MAX_PATH];
472
473    if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) {
474        char *slash = strchr(dbghelpPath, '\\');
475        if (slash) {
476            strcpy(slash + 1, "DBGHELP.DLL");
477            dbghelpModule = LoadLibrary(dbghelpPath);
478        }
479    }
480
481    if (!dbghelpModule) {
482        /* load any version we can */
483        dbghelpModule = LoadLibrary("DBGHELP.DLL");
484        if (!dbghelpModule) {
485            zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found");
486            return;
487        }
488    }
489
490    dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump");
491    if (!dbghelp_MiniDumpWriteDump) {
492        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");
493        return;
494    }
495
496#ifdef XCACHE_VERSION_REVISION
497#define REVISION "r" XCACHE_VERSION_REVISION
498#else
499#define REVISION ""
500#endif
501    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());
502#undef REVISION
503
504    oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter);
505}
506/* }}} */
507#else
508/* old signal handlers {{{ */
509typedef void (*xc_sighandler_t)(int);
510#define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL
511#include "util/xc_foreachcoresig.h"
512#undef FOREACH_SIG
513/* }}} */
514static void xcache_signal_handler(int sig);
515static void xcache_restore_crash_handler() /* {{{ */
516{
517#define FOREACH_SIG(sig) do { \
518    if (old_##sig##_handler != xcache_signal_handler) { \
519        signal(sig, old_##sig##_handler); \
520    } \
521    else { \
522        signal(sig, SIG_DFL); \
523    } \
524} while (0)
525#include "util/xc_foreachcoresig.h"
526#undef FOREACH_SIG
527}
528/* }}} */
529static void xcache_init_crash_handler() /* {{{ */
530{
531#define FOREACH_SIG(sig) \
532    old_##sig##_handler = signal(sig, xcache_signal_handler)
533#include "util/xc_foreachcoresig.h"
534#undef FOREACH_SIG
535}
536/* }}} */
537static void xcache_signal_handler(int sig) /* {{{ */
538{
539    xcache_restore_crash_handler();
540    if (xc_coredump_dir && xc_coredump_dir[0]) {
541        if (chdir(xc_coredump_dir) != 0) {
542            /* error, but nothing can do about it
543             * and should'nt print anything which might SEGV again */
544        }
545    }
546    if (xc_disable_on_crash) {
547        xc_disable_on_crash = 0;
548        xc_cacher_disable();
549    }
550    raise(sig);
551}
552/* }}} */
553#endif
554
555/* {{{ incompatible zend extensions handling */
556typedef struct {
557    const char *name;
558    startup_func_t old_startup;
559} xc_incompatible_zend_extension_info_t;
560static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = {
561    { "Zend Optimizer", NULL }
562};
563
564static xc_incompatible_zend_extension_info_t *xc_get_incompatible_zend_extension_info(const char *name)
565{
566    size_t i;
567
568    for (i = 0; i < sizeof(xc_incompatible_zend_extensions) / sizeof(xc_incompatible_zend_extensions[0]); ++i) {
569        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = &xc_incompatible_zend_extensions[i];
570        if (strcmp(incompatible_zend_extension_info->name, name) == 0) {
571            return incompatible_zend_extension_info;
572        }
573    }
574
575    return NULL;
576}
577/* }}} */
578static int xc_incompatible_zend_extension_startup_hook(zend_extension *extension) /* {{{ */
579{
580    xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
581    int status;
582    zend_bool catched = 0;
583    zend_llist old_zend_extensions = zend_extensions;
584    TSRMLS_FETCH();
585
586    /* hide all extensions from it */
587    zend_extensions.head = NULL;
588    zend_extensions.count = 0;
589
590    /* restore */
591    extension->startup = incompatible_zend_extension_info->old_startup;
592    incompatible_zend_extension_info->old_startup = NULL;
593    assert(extension->startup);
594
595    zend_try {
596        status = extension->startup(extension);
597    } zend_catch {
598        catched = 1;
599    } zend_end_try();
600
601    zend_extensions = old_zend_extensions;
602    if (catched) {
603        zend_bailout();
604    }
605    return status;
606}
607/* }}} */
608static int xc_zend_startup(zend_extension *extension) /* {{{ */
609{
610    zend_llist_position lpos;
611    zend_extension *ext;
612
613    ext = (zend_extension *) zend_extensions.head->data;
614    if (strcmp(ext->name, XCACHE_NAME) != 0) {
615        zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name);
616    }
617
618    old_compile_file = zend_compile_file;
619    zend_compile_file = xc_check_initial_compile_file;
620
621    for (ext = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &lpos);
622            ext;
623            ext = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &lpos)) {
624        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(ext->name);
625        if (incompatible_zend_extension_info) {
626            assert(!incompatible_zend_extension_info->old_startup);
627            incompatible_zend_extension_info->old_startup = ext->startup;
628            ext->startup = xc_incompatible_zend_extension_startup_hook;
629        }
630    }
631    return SUCCESS;
632}
633/* }}} */
634static void xc_zend_shutdown(zend_extension *extension) /* {{{ */
635{
636}
637/* }}} */
638/* {{{ zend extension definition structure */
639static zend_extension xc_zend_extension_entry = {
640    XCACHE_NAME,
641    XCACHE_VERSION,
642    XCACHE_AUTHOR,
643    XCACHE_URL,
644    XCACHE_COPYRIGHT,
645    xc_zend_startup,
646    xc_zend_shutdown,
647    NULL,           /* activate_func_t */
648    NULL,           /* deactivate_func_t */
649    NULL,           /* message_handler_func_t */
650    NULL,           /* op_array_handler_func_t */
651    NULL,           /* statement_handler_func_t */
652    NULL,           /* fcall_begin_handler_func_t */
653    NULL,           /* fcall_end_handler_func_t */
654    NULL,           /* op_array_ctor_func_t */
655    NULL,           /* op_array_dtor_func_t */
656    STANDARD_ZEND_EXTENSION_PROPERTIES
657};
658/* }}} */
659
660/* {{{ PHP_INI */
661PHP_INI_BEGIN()
662    PHP_INI_ENTRY1     ("xcache.coredump_directory",      "", PHP_INI_SYSTEM, xcache_OnUpdateString,   &xc_coredump_dir)
663    PHP_INI_ENTRY1_EX  ("xcache.disable_on_crash",       "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_disable_on_crash, zend_ini_boolean_displayer_cb)
664    PHP_INI_ENTRY1_EX  ("xcache.test",                   "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_test,             zend_ini_boolean_displayer_cb)
665    STD_PHP_INI_BOOLEAN("xcache.experimental",           "0", PHP_INI_ALL,    OnUpdateBool,        experimental,      zend_xcache_globals, xcache_globals)
666PHP_INI_END()
667/* }}} */
668static PHP_MINFO_FUNCTION(xcache) /* {{{ */
669{
670    php_info_print_table_start();
671    php_info_print_table_row(2, "XCache Version", XCACHE_VERSION);
672#ifdef XCACHE_VERSION_REVISION
673    php_info_print_table_row(2, "Revision", "r" XCACHE_VERSION_REVISION);
674#endif
675    php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
676    php_info_print_table_end();
677
678    DISPLAY_INI_ENTRIES();
679}
680/* }}} */
681static PHP_MINIT_FUNCTION(xcache) /* {{{ */
682{
683#ifndef PHP_GINIT
684    ZEND_INIT_MODULE_GLOBALS(xcache, xc_init_globals, xc_shutdown_globals);
685#endif
686    REGISTER_INI_ENTRIES();
687
688    if (xc_coredump_dir && xc_coredump_dir[0]) {
689        xcache_init_crash_handler();
690    }
691
692    xc_init_constant(module_number TSRMLS_CC);
693    xc_shm_init_modules();
694
695    /* must be the first */
696    xcache_zend_extension_add(&xc_zend_extension_entry, 1);
697#ifdef HAVE_XCACHE_OPTIMIZER
698    xc_optimizer_startup_module();
699#endif
700#ifdef HAVE_XCACHE_CACHER
701    xc_cacher_startup_module();
702#endif
703#ifdef HAVE_XCACHE_COVERAGER
704    xc_coverager_startup_module();
705#endif
706#ifdef HAVE_XCACHE_DISASSEMBLER
707    xc_disassembler_startup_module();
708#endif
709
710    return SUCCESS;
711
712err_init:
713    return FAILURE;
714}
715/* }}} */
716static PHP_MSHUTDOWN_FUNCTION(xcache) /* {{{ */
717{
718    if (old_compile_file && zend_compile_file == xc_check_initial_compile_file) {
719        zend_compile_file = old_compile_file;
720        old_compile_file = NULL;
721    }
722
723    if (xc_coredump_dir && xc_coredump_dir[0]) {
724        xcache_restore_crash_handler();
725    }
726    if (xc_coredump_dir) {
727        pefree(xc_coredump_dir, 1);
728        xc_coredump_dir = NULL;
729    }
730#ifndef PHP_GINIT
731#   ifdef ZTS
732    ts_free_id(xcache_globals_id);
733#   else
734    xc_shutdown_globals(&xcache_globals TSRMLS_CC);
735#   endif
736#endif
737
738    UNREGISTER_INI_ENTRIES();
739    xcache_zend_extension_remove(&xc_zend_extension_entry);
740    return SUCCESS;
741}
742/* }}} */
743/* {{{ module dependencies */
744#ifdef STANDARD_MODULE_HEADER_EX
745static zend_module_dep xcache_module_deps[] = {
746    ZEND_MOD_REQUIRED("standard")
747    ZEND_MOD_CONFLICTS("apc")
748    ZEND_MOD_CONFLICTS("eAccelerator")
749    ZEND_MOD_CONFLICTS("Turck MMCache")
750    ZEND_MOD_END
751};
752#endif
753/* }}} */ 
754/* {{{ module definition structure */
755zend_module_entry xcache_module_entry = {
756#ifdef STANDARD_MODULE_HEADER_EX
757    STANDARD_MODULE_HEADER_EX,
758    NULL,
759    xcache_module_deps,
760#else
761    STANDARD_MODULE_HEADER,
762#endif
763    XCACHE_NAME,
764    xcache_functions,
765    PHP_MINIT(xcache),
766    PHP_MSHUTDOWN(xcache),
767    NULL, /* RINIT */
768    NULL, /* RSHUTDOWN */
769    PHP_MINFO(xcache),
770    XCACHE_VERSION,
771#ifdef PHP_GINIT
772    PHP_MODULE_GLOBALS(xcache),
773    PHP_GINIT(xcache),
774    PHP_GSHUTDOWN(xcache),
775#endif
776#ifdef ZEND_ENGINE_2
777    NULL /* ZEND_MODULE_POST_ZEND_DEACTIVATE_N */,
778#else
779    NULL,
780    NULL,
781#endif
782    STANDARD_MODULE_PROPERTIES_EX
783};
784
785#ifdef COMPILE_DL_XCACHE
786ZEND_GET_MODULE(xcache)
787#endif
788/* }}} */
Note: See TracBrowser for help on using the repository browser.