diff --git a/sapi/apache2handler/apache_config.c b/sapi/apache2handler/apache_config.c
index a7dbbeb..7456f85 100644
--- a/sapi/apache2handler/apache_config.c
+++ b/sapi/apache2handler/apache_config.c
@@ -181,18 +181,18 @@ char *get_php_config(void *conf, char *name, size_t name_len)
 	return "";
 }
 
-void apply_config(void *dummy)
+void apply_config(request_rec *r)
 {
-	php_conf_rec *d = dummy;
 	char *str;
 	uint str_len;
 	php_dir_entry *data;
+	php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php5_module);
 	
-	for (zend_hash_internal_pointer_reset(&d->config);
-			zend_hash_get_current_key_ex(&d->config, &str, &str_len, NULL, 0, 
+	for (zend_hash_internal_pointer_reset(&c->config);
+			zend_hash_get_current_key_ex(&c->config, &str, &str_len, NULL, 0, 
 				NULL) == HASH_KEY_IS_STRING;
-			zend_hash_move_forward(&d->config)) {
-		if (zend_hash_get_current_data(&d->config, (void **) &data) == SUCCESS) {
+			zend_hash_move_forward(&c->config)) {
+		if (zend_hash_get_current_data(&c->config, (void **) &data) == SUCCESS) {
 			phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value));
 			if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) {
 				phpapdebug((stderr, "..FAILED\n"));
@@ -201,6 +201,19 @@ void apply_config(void *dummy)
 	}
 }
 
+void restore_config(request_rec *r) {
+	char *str;
+	uint str_len;
+	php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php5_module);
+
+	for (zend_hash_internal_pointer_reset(&c->config);
+		zend_hash_get_current_key_ex(&c->config, &str, &str_len, NULL, 0,  NULL) == HASH_KEY_IS_STRING;
+		zend_hash_move_forward(&c->config)
+	) {
+		zend_restore_ini_entry(str, str_len, ZEND_INI_STAGE_SHUTDOWN);
+	}
+}
+
 const command_rec php_dir_cmds[] =
 {
 	AP_INIT_TAKE2("php_value", php_apache_value_handler, NULL, OR_OPTIONS, "PHP Value Modifier"),
diff --git a/sapi/apache2handler/php_apache.h b/sapi/apache2handler/php_apache.h
index d0673e1..82d53ae 100644
--- a/sapi/apache2handler/php_apache.h
+++ b/sapi/apache2handler/php_apache.h
@@ -33,7 +33,7 @@ extern char *apache2_php_ini_path_override;
 
 /* The server_context used by PHP */
 typedef struct php_struct {
-	int state;
+	int state;	/* WHAT IS THIS DOING? */
 	request_rec *r;
 	apr_bucket_brigade *brigade;
 	/* stat structure of the current file */
@@ -42,7 +42,9 @@ typedef struct php_struct {
 #else
 	struct stat finfo;
 #endif
-	/* Whether or not we've processed PHP in the output filters yet. */
+	/* saved &SG(server_context), for proper cleanup */
+	void **server_context;
+	/* Whether or not we are done with the request */
 	int request_processed;
 	/* final content type */
 	char *content_type;
@@ -51,7 +53,8 @@ typedef struct php_struct {
 void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf);
 void *create_php_config(apr_pool_t *p, char *dummy);
 char *get_php_config(void *conf, char *name, size_t name_len);
-void apply_config(void *);
+void apply_config(request_rec *);
+void restore_config(request_rec *);
 extern const command_rec php_dir_cmds[];
 void php_ap2_register_hook(apr_pool_t *p);
 
diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c
index 71002c7..885dc94 100644
--- a/sapi/apache2handler/php_functions.c
+++ b/sapi/apache2handler/php_functions.c
@@ -96,7 +96,11 @@ PHP_FUNCTION(virtual)
 
 	/* Ensure that the ap_r* layer for the main request is flushed, to
 	 * work around http://issues.apache.org/bugzilla/show_bug.cgi?id=17629 */
-	ap_rflush(rr->main);
+	/* ap_rflush(rr->main);
+	 * DISABLED because it causes a pool destroy of the still running request,
+	 * sometimes, resulting in a crash later. Ask php@bof.de for a backtrace
+	 * if you want to investigate this.
+	 */
 
 	if (ap_run_sub_req(rr)) {
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - request execution failed", filename);
diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c
index 088ff77..8d001fb 100644
--- a/sapi/apache2handler/sapi_apache2.c
+++ b/sapi/apache2handler/sapi_apache2.c
@@ -75,13 +75,11 @@ char *apache2_php_ini_path_override = NULL;
 static int
 php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
 {
-	request_rec *r;
 	php_struct *ctx;
 
 	ctx = SG(server_context);
-	r = ctx->r;
 
-	if (ap_rwrite(str, str_length, r) < 0) {
+	if (ap_rwrite(str, str_length, ctx->r) < 0) {
 		php_handle_aborted_connection();
 	}
 
@@ -185,10 +183,8 @@ php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
 {
 	apr_size_t len, tlen=0;
 	php_struct *ctx = SG(server_context);
-	request_rec *r;
 	apr_bucket_brigade *brigade;
 
-	r = ctx->r;
 	brigade = ctx->brigade;
 	len = count_bytes;
 
@@ -198,7 +194,7 @@ php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
 	 * need to make sure that if data is available we fill the buffer completely.
 	 */
 
-	while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
+	while (ap_get_brigade(ctx->r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
 		apr_brigade_flatten(brigade, buf, &len);
 		apr_brigade_cleanup(brigade);
 		tlen += len;
@@ -461,18 +457,28 @@ php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp
 	return OK;
 }
 
-static apr_status_t php_server_context_cleanup(void *data_)
+static apr_status_t php_server_context_cleanup(void *data)
 {
-	void **data = data_;
-	*data = NULL;
+	php_struct *ctx = data;
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_server_context_cleanup ctx=%x request_processed=%d r=%x r->pool=%x",
+			ctx, ctx->request_processed, ctx->r, ctx->r->pool);
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_server_context_cleanup ctx=%x *ctx->server_context=%x ctx->server_context=%x &SG(server_context)=%x",
+			ctx, *ctx->server_context, ctx->server_context, &SG(server_context));
+	if (*ctx->server_context == ctx) {
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_server_context_cleanup ctx=%x ctx->server_context=%x CLEANUP",
+			ctx, ctx->server_context);
+		*ctx->server_context = NULL;
+	}
 	return APR_SUCCESS;
 }
 
-static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC)
+static int php_apache_request_ctor(php_struct *ctx TSRMLS_DC)
 {
 	char *content_length;
 	const char *auth;
+	request_rec *r = ctx->r;
 
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_apache_request_ctor ctx=%x r=%x", ctx, r);
 	SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status;
 	SG(request_info).content_type = apr_table_get(r->headers_in, "Content-Type");
 	SG(request_info).query_string = apr_pstrdup(r->pool, r->args);
@@ -497,104 +503,114 @@ static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC)
 		SG(request_info).auth_user = estrdup(r->user);
 	}
 
-	ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
+	r->user = apr_pstrdup(r->pool, SG(request_info).auth_user);
 
 	return php_request_startup(TSRMLS_C);
 }
 
-static void php_apache_request_dtor(request_rec *r TSRMLS_DC)
+static void php_apache_request_dtor(php_struct *ctx TSRMLS_DC)
 {
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_apache_request_dtor ctx=%x r=%x", ctx, ctx->r);
 	php_request_shutdown(NULL);
+	ctx->request_processed = 1;
 }
 
-static void php_apache_ini_dtor(request_rec *r, request_rec *p TSRMLS_DC)
+static void php_apache_ini_dtor(php_struct *ctx, php_struct *prev_ctx TSRMLS_DC)
 {
-	if (strcmp(r->protocol, "INCLUDED")) {
-		zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try();
-	} else {
-typedef struct {
-	HashTable config;
-} php_conf_rec;
-		char *str;
-		uint str_len;
-		php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php5_module);
-
-		for (zend_hash_internal_pointer_reset(&c->config);
-			zend_hash_get_current_key_ex(&c->config, &str, &str_len, NULL, 0,  NULL) == HASH_KEY_IS_STRING;
-			zend_hash_move_forward(&c->config)
-		) {
-			zend_restore_ini_entry(str, str_len, ZEND_INI_STAGE_SHUTDOWN);
-		}
-	}
-	if (p) {
-		((php_struct *)SG(server_context))->r = p;
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_apache_ini_dtor ctx=%x r=%x prev_ctx=%x", ctx, ctx->r, prev_ctx);
+	if (prev_ctx) {
+		restore_config(ctx->r);
 	} else {
-		apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
+		zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try();
 	}
+	SG(server_context) = prev_ctx;
 }
 
 static int php_handler(request_rec *r)
 {
-	php_struct * volatile ctx;
-	void *conf;
-	apr_bucket_brigade * volatile brigade;
+	php_struct *ctx;
+	php_struct *prev_ctx;
 	apr_bucket *bucket;
 	apr_status_t rv;
-	request_rec * volatile parent_req = NULL;
 	TSRMLS_FETCH();
 
-#define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req TSRMLS_CC);
-
-	conf = ap_get_module_config(r->per_dir_config, &php5_module);
-
-	/* apply_config() needs r in some cases, so allocate server_context early */
-	ctx = SG(server_context);
-	if (ctx == NULL || (ctx && ctx->request_processed && !strcmp(r->protocol, "INCLUDED"))) {
-normal:
-		ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
-		/* register a cleanup so we clear out the SG(server_context)
-		 * after each request. Note: We pass in the pointer to the
-		 * server_context in case this is handled by a different thread.
-		 */
-		apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
-		ctx->r = r;
-		ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */
-	} else {
-		parent_req = ctx->r;
-		ctx->r = r;
+	/* detect reentry. In case of reentry, prev_ctx will be non-NULL */
+	prev_ctx = SG(server_context);
+	if (prev_ctx) {
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_handler OLD ctx=%x ctx->request_processed=%d ctx->r=%x ctx->r->pool=%x",
+				prev_ctx, prev_ctx->request_processed, prev_ctx->r, prev_ctx->r->pool);
+		if (prev_ctx->request_processed) {
+			prev_ctx = NULL;
+		}
+	}
+	/* ALWAYS run with a freshly allocated ctx, to that the lifetime of the
+	 * active ctx is coupled to the r->pool it is allocated from. We must set
+	 * SG(server_context) early, here, because apply_config() is said to require
+	 * a valid ctx, and this is the most valid ctx we can have.
+	 */
+	ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
+	ctx->r = r;
+	/* register a cleanup so we clear out the SG(server_context) when
+	 * r->pool is destroyed.
+	 *
+	 * NOTE: We pass in ctx itself, and will validate in, in the cleanup
+	 * function php_server_context_cleanup, that we still have
+	 * (*ctx->server_context == ctx), so that the cleanup will even
+	 * work when called in a different thread, and will not disturb
+	 * the active server_context when cleanup comes late - this happens
+	 * with Apache 2.4.
+	 */
+	ctx->server_context = &SG(server_context);
+	apr_pool_cleanup_register(r->pool, (void *)ctx, php_server_context_cleanup, apr_pool_cleanup_null);
+	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "php_handler NEW ctx=%x r=%x r->pool=%x &SG(server_context)=%x",
+			ctx, r, r->pool, &SG(server_context));
+
+	apply_config(r);
+
+	if (    strcmp(r->handler, PHP_MAGIC_TYPE)
+	     && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE)
+	     && strcmp(r->handler, PHP_SCRIPT)
+	     && (    !AP2(xbithack)
+		  || strcmp(r->handler, "text/html")
+		  || !(r->finfo.protection & APR_UEXECUTE)
+	        )
+	   ) {
+		/* No PHP request. Decline to handle. */
+		php_apache_ini_dtor(ctx, prev_ctx TSRMLS_CC);
+		return DECLINED;
 	}
-	apply_config(conf);
 
-	if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) {
-		/* Check for xbithack in this case. */
-		if (!AP2(xbithack) || strcmp(r->handler, "text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
-			PHPAP_INI_OFF;
-			return DECLINED;
-		}
+	if (prev_ctx) {
+		/* REENTRY. Not good. Fail. */
+		ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+				"script '%s' PHP reentry forbidden, invoked from '%s'",
+				r->filename, ctx->r->filename);
+		php_apache_ini_dtor(ctx, prev_ctx TSRMLS_CC);
+		return HTTP_NOT_FOUND;
 	}
 
 	/* Give a 404 if PATH_INFO is used but is explicitly disabled in
 	 * the configuration; default behaviour is to accept. */
 	if (r->used_path_info == AP_REQ_REJECT_PATH_INFO
 		&& r->path_info && r->path_info[0]) {
-		PHPAP_INI_OFF;
+		php_apache_ini_dtor(ctx, prev_ctx TSRMLS_CC);
 		return HTTP_NOT_FOUND;
 	}
 
 	/* handle situations where user turns the engine off */
 	if (!AP2(engine)) {
-		PHPAP_INI_OFF;
+		php_apache_ini_dtor(ctx, prev_ctx TSRMLS_CC);
 		return DECLINED;
 	}
 
 	if (r->finfo.filetype == 0) {
 		php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r TSRMLS_CC);
-		PHPAP_INI_OFF;
+		php_apache_ini_dtor(ctx, prev_ctx TSRMLS_CC);
 		return HTTP_NOT_FOUND;
 	}
 	if (r->finfo.filetype == APR_DIR) {
 		php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r TSRMLS_CC);
-		PHPAP_INI_OFF;
+		php_apache_ini_dtor(ctx, prev_ctx TSRMLS_CC);
 		return HTTP_FORBIDDEN;
 	}
 
@@ -610,39 +626,10 @@ normal:
 
 zend_first_try {
 
-	if (ctx == NULL) {
-		brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
-		ctx = SG(server_context);
-		ctx->brigade = brigade;
+	ctx->brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
 
-		if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) {
-			zend_bailout();
-		}
-	} else {
-		if (!parent_req) {
-			parent_req = ctx->r;
-		}
-		if (parent_req && parent_req->handler &&
-				strcmp(parent_req->handler, PHP_MAGIC_TYPE) &&
-				strcmp(parent_req->handler, PHP_SOURCE_MAGIC_TYPE) &&
-				strcmp(parent_req->handler, PHP_SCRIPT)) {
-			if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) {
-				zend_bailout();
-			}
-		}
-
-		/*
-		 * check if coming due to ErrorDocument
-		 * We make a special exception of 413 (Invalid POST request) as the invalidity of the request occurs
-		 * during processing of the request by PHP during POST processing. Therefor we need to re-use the exiting
-		 * PHP instance to handle the request rather then creating a new one.
-		*/
-		if (parent_req && parent_req->status != HTTP_OK && parent_req->status != 413 && strcmp(r->protocol, "INCLUDED")) {
-			parent_req = NULL;
-			goto normal;
-		}
-		ctx->r = r;
-		brigade = ctx->brigade;
+	if (php_apache_request_ctor(ctx TSRMLS_CC)!=SUCCESS) {
+		zend_bailout();
 	}
 
 	if (AP2(last_modified)) {
@@ -663,34 +650,25 @@ zend_first_try {
 		zfd.free_filename = 0;
 		zfd.opened_path = NULL;
 
-		if (!parent_req) {
-			php_execute_script(&zfd TSRMLS_CC);
-		} else {
-			zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &zfd);
-		}
+		php_execute_script(&zfd TSRMLS_CC);
 
 		apr_table_set(r->notes, "mod_php_memory_usage",
-			apr_psprintf(ctx->r->pool, "%" APR_SIZE_T_FMT, zend_memory_peak_usage(1 TSRMLS_CC)));
+			apr_psprintf(r->pool, "%" APR_SIZE_T_FMT, zend_memory_peak_usage(1 TSRMLS_CC)));
 	}
 
 } zend_end_try();
 
-	if (!parent_req) {
-		php_apache_request_dtor(r TSRMLS_CC);
-		ctx->request_processed = 1;
-		bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
-		APR_BRIGADE_INSERT_TAIL(brigade, bucket);
+	php_apache_request_dtor(ctx TSRMLS_CC);
+	bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
+	APR_BRIGADE_INSERT_TAIL(ctx->brigade, bucket);
 
-		rv = ap_pass_brigade(r->output_filters, brigade);
-		if (rv != APR_SUCCESS || r->connection->aborted) {
+	rv = ap_pass_brigade(r->output_filters, ctx->brigade);
+	if (rv != APR_SUCCESS || r->connection->aborted) {
 zend_first_try {
-			php_handle_aborted_connection();
+		php_handle_aborted_connection();
 } zend_end_try();
-		}
-		apr_brigade_cleanup(brigade);
-	} else {
-		ctx->r = parent_req;
 	}
+	apr_brigade_cleanup(ctx->brigade);
 
 	return OK;
 }
