Index: /trunk/mod_cacher/xc_cacher.c
===================================================================
--- /trunk/mod_cacher/xc_cacher.c	(revision 1045)
+++ /trunk/mod_cacher/xc_cacher.c	(revision 1047)
@@ -3254,5 +3254,5 @@
 
 	xc_sandbox_module_init(module_number TSRMLS_CC);
-	return xcache_zend_extension_prepend(&xc_cacher_zend_extension_entry);
+	return xcache_zend_extension_add(&xc_cacher_zend_extension_entry, 0);
 
 err_init:
Index: /trunk/xcache/xc_extension.c
===================================================================
--- /trunk/xcache/xc_extension.c	(revision 1045)
+++ /trunk/xcache/xc_extension.c	(revision 1047)
@@ -5,5 +5,5 @@
 
 
-int xcache_zend_extension_prepend(zend_extension *new_extension) /* {{{ */
+int xcache_zend_extension_add(zend_extension *new_extension, zend_bool prepend) /* {{{ */
 {
 	zend_extension extension;
@@ -14,6 +14,11 @@
 	zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
 
-	zend_llist_prepend_element(&zend_extensions, &extension);
-	TRACE("%s", "prepended");
+	if (prepend) {
+		zend_llist_prepend_element(&zend_extensions, &extension);
+	}
+	else {
+		zend_llist_add_element(&zend_extensions, &extension);
+	}
+	TRACE("%s", "registered");
 	return SUCCESS;
 }
@@ -51,42 +56,4 @@
 /* }}} */
 
-int xcache_zend_extension_count_by_prefix(zend_llist *l, const char *extension_name_prefix) /* {{{ */
-{
-	zend_llist_element *element;
-	size_t n = strlen(extension_name_prefix);
-	int count = 0;
-
-	for (element = zend_extensions.head; element; element = element->next) {
-		zend_extension *extension = (zend_extension *) element->data;
-
-		if (strncmp(extension->name, extension_name_prefix, n) == 0) {
-			++count;
-		}
-	}
-	return count;
-}
-/* }}} */
-void xcache_zend_extension_unlink_by_prefix(xc_stack_t *linked, zend_llist *l, const char *extension_name_prefix) /* {{{ */
-{
-	size_t n = strlen(extension_name_prefix);
-	zend_llist_element *unlinked = NULL;
-	zend_llist_element *element, *next;
-
-	for (element = zend_extensions.head; element; element = next) {
-		zend_extension *extension = (zend_extension *) element->data;
-		next = element->next;
-
-		if (strncmp(extension->name, extension_name_prefix, n) == 0) {
-			xcache_llist_unlink(l, element);
-			xc_stack_push(linked, element);
-		}
-	}
-
-	for (element = zend_extensions.head; element; element = next) {
-		zend_extension *extension = (zend_extension *) element->data;
-		next = element->next;
-	}
-}
-/* }}} */
 void xcache_llist_prepend(zend_llist *l, zend_llist_element *element) /* {{{ */
 {
Index: /trunk/xcache/xc_extension.h
===================================================================
--- /trunk/xcache/xc_extension.h	(revision 1045)
+++ /trunk/xcache/xc_extension.h	(revision 1047)
@@ -8,8 +8,6 @@
 #include "util/xc_stack.h"
 #include "zend_extensions.h"
-int xcache_zend_extension_prepend(zend_extension *new_extension);
+int xcache_zend_extension_add(zend_extension *new_extension, zend_bool prepend);
 int xcache_zend_extension_remove(zend_extension *extension);
-int xcache_zend_extension_count_by_prefix(zend_llist *l, const char *extension_name_prefix);
-void xcache_zend_extension_unlink_by_prefix(xc_stack_t *unlinked, zend_llist *l, const char *extension_name_prefix);
 
 void xcache_llist_prepend(zend_llist *l, zend_llist_element *element);
Index: /trunk/mod_coverager/xc_coverager.c
===================================================================
--- /trunk/mod_coverager/xc_coverager.c	(revision 1045)
+++ /trunk/mod_coverager/xc_coverager.c	(revision 1047)
@@ -671,5 +671,5 @@
 	}
 
-	return xcache_zend_extension_prepend(&xc_coverager_zend_extension_entry);
+	return xcache_zend_extension_add(&xc_coverager_zend_extension_entry, 0);
 }
 /* }}} */
Index: /trunk/xcache.c
===================================================================
--- /trunk/xcache.c	(revision 1045)
+++ /trunk/xcache.c	(revision 1047)
@@ -543,53 +543,79 @@
 #endif
 
-static startup_func_t xc_last_ext_old_startup;
-static xc_stack_t xc_llist_zend_extensions; /* (zend_extension *) */
-static int xc_zend_startup_last_hook(zend_extension *extension) /* {{{ */
-{
-	zend_extension *ext = zend_get_extension(XCACHE_NAME);
-	if (ext) {
-		zend_error(E_WARNING, "Module '" XCACHE_NAME "' already loaded");
-	}
+/* {{{ incompatible zend extensions handling */
+typedef struct {
+	const char *name;
+	startup_func_t old_startup;
+} xc_incompatible_zend_extension_info_t;
+static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = {
+	{ "Zend Optimizer", NULL }
+};
+
+static xc_incompatible_zend_extension_info_t *xc_get_incompatible_zend_extension_info(const char *name)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(xc_incompatible_zend_extensions) / sizeof(xc_incompatible_zend_extensions[0]); ++i) {
+		xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = &xc_incompatible_zend_extensions[i];
+		if (strcmp(incompatible_zend_extension_info->name, name) == 0) {
+			return incompatible_zend_extension_info;
+		}
+	}
+
+	return NULL;
+}
+/* }}} */
+static int xc_incompatible_zend_extension_startup_hook(zend_extension *extension) /* {{{ */
+{
+	xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
+	int status;
+	zend_bool catched = 0;
+	zend_llist old_zend_extensions = zend_extensions;
+	TSRMLS_FETCH();
+
+	/* hide all extensions from it */
+	zend_extensions.head = NULL;
+	zend_extensions.count = 0;
+
 	/* restore */
-	extension->startup = xc_last_ext_old_startup;
-	extension->startup = xc_last_ext_old_startup;
-	xc_last_ext_old_startup = NULL;
-	if (extension->startup) {
-		if (extension->startup(extension) != SUCCESS) {
-			return FAILURE;
-		}
-	}
-
-	assert(xc_stack_count(&xc_llist_zend_extensions));
-	while (xc_stack_count(&xc_llist_zend_extensions)) {
-		zend_llist_element *p = (zend_llist_element *) xc_stack_pop(&xc_llist_zend_extensions);
-		xcache_llist_prepend(&zend_extensions, p);
-	}
-	xc_stack_destroy(&xc_llist_zend_extensions);
-	return SUCCESS;
+	extension->startup = incompatible_zend_extension_info->old_startup;
+	incompatible_zend_extension_info->old_startup = NULL;
+	assert(extension->startup);
+
+	zend_try {
+		status = extension->startup(extension);
+	} zend_catch {
+		catched = 1;
+	} zend_end_try();
+
+	zend_extensions = old_zend_extensions;
+	if (catched) {
+		zend_bailout();
+	}
+	return status;
 }
 /* }}} */
 static int xc_zend_startup(zend_extension *extension) /* {{{ */
 {
+	zend_llist_position lpos;
+	zend_extension *ext;
+
+	ext = (zend_extension *) zend_extensions.head->data;
+	if (strcmp(ext->name, XCACHE_NAME) != 0) {
+		zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name);
+	}
+
 	old_compile_file = zend_compile_file;
 	zend_compile_file = xc_check_initial_compile_file;
 
-	if (1 || xcache_zend_extension_count_by_prefix(&zend_extensions, XCACHE_NAME) != zend_llist_count(&zend_extensions)) {
-		zend_llist_position lpos;
-		zend_extension *ext = (zend_extension *) zend_extensions.head->data;
-		assert(ext);
-
-		if (strcmp(ext->name, XCACHE_NAME) != 0) {
-			zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name);
-		}
-
-		/* hide XCache modules */
-		xc_stack_init(&xc_llist_zend_extensions);
-		xcache_zend_extension_unlink_by_prefix(&xc_llist_zend_extensions, &zend_extensions, XCACHE_NAME);
-
-		ext = (zend_extension *) zend_llist_get_last_ex(&zend_extensions, &lpos);
-		assert(ext);
-		xc_last_ext_old_startup = ext->startup;
-		ext->startup = xc_zend_startup_last_hook;
+	for (ext = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &lpos);
+			ext;
+			ext = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &lpos)) {
+		xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
+		if (incompatible_zend_extension_info) {
+			assert(!incompatible_zend_extension_info->old_startup);
+			incompatible_zend_extension_info->old_startup = ext->startup;
+			ext->startup = xc_incompatible_zend_extension_startup_hook;
+		}
 	}
 	return SUCCESS;
@@ -657,5 +683,12 @@
 	xc_shm_init_modules();
 
-	/* ZendExtension is registered in reverse order for prepend by XCache */
+	/* must be the first */
+	xcache_zend_extension_add(&xc_zend_extension_entry, 1);
+#ifdef HAVE_XCACHE_OPTIMIZER
+	xc_optimizer_startup_module();
+#endif
+#ifdef HAVE_XCACHE_CACHER
+	xc_cacher_startup_module();
+#endif
 #ifdef HAVE_XCACHE_COVERAGER
 	xc_coverager_startup_module();
@@ -664,12 +697,4 @@
 	xc_disassembler_startup_module();
 #endif
-#ifdef HAVE_XCACHE_CACHER
-	xc_cacher_startup_module();
-#endif
-#ifdef HAVE_XCACHE_OPTIMIZER
-	xc_optimizer_startup_module();
-#endif
-	/* must be the first */
-	xcache_zend_extension_prepend(&xc_zend_extension_entry);
 
 	return SUCCESS;
Index: /trunk/mod_optimizer/xc_optimizer.c
===================================================================
--- /trunk/mod_optimizer/xc_optimizer.c	(revision 1045)
+++ /trunk/mod_optimizer/xc_optimizer.c	(revision 1047)
@@ -667,5 +667,5 @@
 {
 	REGISTER_INI_ENTRIES();
-	return xcache_zend_extension_prepend(&xc_optimizer_zend_extension_entry);
+	return xcache_zend_extension_add(&xc_optimizer_zend_extension_entry, 0);
 }
 /* }}} */
