| 545 | | static startup_func_t xc_last_ext_old_startup; |
| 546 | | static xc_stack_t xc_llist_zend_extensions; /* (zend_extension *) */ |
| 547 | | static int xc_zend_startup_last_hook(zend_extension *extension) /* {{{ */ |
| 548 | | { |
| 549 | | zend_extension *ext = zend_get_extension(XCACHE_NAME); |
| 550 | | if (ext) { |
| 551 | | zend_error(E_WARNING, "Module '" XCACHE_NAME "' already loaded"); |
| 552 | | } |
| | 545 | /* {{{ incompatible zend extensions handling */ |
| | 546 | typedef struct { |
| | 547 | const char *name; |
| | 548 | startup_func_t old_startup; |
| | 549 | } xc_incompatible_zend_extension_info_t; |
| | 550 | static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = { |
| | 551 | { "Zend Optimizer", NULL } |
| | 552 | }; |
| | 553 | |
| | 554 | static 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 | /* }}} */ |
| | 568 | static 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 | |
| 554 | | extension->startup = xc_last_ext_old_startup; |
| 555 | | extension->startup = xc_last_ext_old_startup; |
| 556 | | xc_last_ext_old_startup = NULL; |
| 557 | | if (extension->startup) { |
| 558 | | if (extension->startup(extension) != SUCCESS) { |
| 559 | | return FAILURE; |
| 560 | | } |
| 561 | | } |
| 562 | | |
| 563 | | assert(xc_stack_count(&xc_llist_zend_extensions)); |
| 564 | | while (xc_stack_count(&xc_llist_zend_extensions)) { |
| 565 | | zend_llist_element *p = (zend_llist_element *) xc_stack_pop(&xc_llist_zend_extensions); |
| 566 | | xcache_llist_prepend(&zend_extensions, p); |
| 567 | | } |
| 568 | | xc_stack_destroy(&xc_llist_zend_extensions); |
| 569 | | return SUCCESS; |
| | 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; |
| 577 | | if (1 || xcache_zend_extension_count_by_prefix(&zend_extensions, XCACHE_NAME) != zend_llist_count(&zend_extensions)) { |
| 578 | | zend_llist_position lpos; |
| 579 | | zend_extension *ext = (zend_extension *) zend_extensions.head->data; |
| 580 | | assert(ext); |
| 581 | | |
| 582 | | if (strcmp(ext->name, XCACHE_NAME) != 0) { |
| 583 | | zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name); |
| 584 | | } |
| 585 | | |
| 586 | | /* hide XCache modules */ |
| 587 | | xc_stack_init(&xc_llist_zend_extensions); |
| 588 | | xcache_zend_extension_unlink_by_prefix(&xc_llist_zend_extensions, &zend_extensions, XCACHE_NAME); |
| 589 | | |
| 590 | | ext = (zend_extension *) zend_llist_get_last_ex(&zend_extensions, &lpos); |
| 591 | | assert(ext); |
| 592 | | xc_last_ext_old_startup = ext->startup; |
| 593 | | ext->startup = xc_zend_startup_last_hook; |
| | 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 | } |