# [PATCH] apache2handler memory leak fix

- Thread: https://externals.io/message/10583
- Original archive: https://news-web.php.net/php.internals/10583
- Started by Joe Orton on 2004-06-18T10:30:32+00:00
- Messages: 3
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #10583 — Joe Orton — 2004-06-18T10:30:32+00:00

URL: https://externals.io/message/10583#10583

It's simpler to just use the ap_r* interfaces in the the handler SAPI
for 2.0, this improves network usage by allowing httpd to buffer as
necessary, and fixes a bug where ub_write is unnecessarily pmemdup'ing
the string (it could have used a transient bucket to avoid that; the
apache2filter got this right), and stops re-using an output brigade
which is now or at least will soon be a 2.0 API violation.

(this restores constant memory use for an arbitrary length response)

--- php-4.3.7/sapi/apache2handler/sapi_apache2.c.handler
+++ php-4.3.7/sapi/apache2handler/sapi_apache2.c
@@ -67,30 +67,15 @@
 static int
 php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
 {
-	apr_bucket *bucket;
-	apr_bucket_brigade *brigade;
 	request_rec *r;
 	php_struct *ctx;
-	char *copy_str;
-
-	if (str_length == 0) {
-		return 0;
-	}
 
 	ctx = SG(server_context);
 	r = ctx->r;
-	brigade = ctx->brigade;
 	
-	copy_str = apr_pmemdup( r->pool, str, str_length);
-	bucket = apr_bucket_pool_create(copy_str, str_length, r->pool, r->connection->bucket_alloc);
-						 
-	APR_BRIGADE_INSERT_TAIL(brigade, bucket);
-
-	if (ap_pass_brigade(r->output_filters, brigade) != APR_SUCCESS || r->connection->aborted) {
+	if (ap_rwrite(str, str_length, r) < 0) {
 		php_handle_aborted_connection();
 	}
-	/* Ensure this brigade is empty for the next usage. */
-	apr_brigade_cleanup(brigade);
 	
 	return str_length; /* we always consume all the data passed to us. */
 }
@@ -245,8 +230,6 @@
 php_apache_sapi_flush(void *server_context)
 {
 	php_struct *ctx;
-	apr_bucket_brigade *brigade;
-	apr_bucket *bucket;
 	request_rec *r;
 	TSRMLS_FETCH();
 
@@ -259,20 +242,15 @@
 	}
 
 	r = ctx->r;
-	brigade = ctx->brigade;
 
 	sapi_send_headers(TSRMLS_C);
 
 	r->status = SG(sapi_headers).http_response_code;
 	SG(headers_sent) = 1;
 
-	/* Send a flush bucket down the filter chain. */
-	bucket = apr_bucket_flush_create(r->connection->bucket_alloc);
-	APR_BRIGADE_INSERT_TAIL(brigade, bucket);
-	if (ap_pass_brigade(r->output_filters, brigade) != APR_SUCCESS || r->connection->aborted) {
+	if (ap_rflush(r) < 0 || r->connection->aborted) {
 		php_handle_aborted_connection();
 	}
-	apr_brigade_cleanup(brigade);
 }
 
 static void php_apache_sapi_log_message(char *msg)

---

## #10585 — magnus@php.net — 2004-06-18T12:13:05+00:00

URL: https://externals.io/message/10583#10585 · In reply to: #10583

Hi!


> It's simpler to just use the ap_r* interfaces in the the handler SAPI
> for 2.0, this improves network usage by allowing httpd to buffer as
> necessary, and fixes a bug where ub_write is unnecessarily pmemdup'ing
> the string (it could have used a transient bucket to avoid that; the
> apache2filter got this right), and stops re-using an output brigade
> which is now or at least will soon be a 2.0 API violation.
>
> (this restores constant memory use for an arbitrary length response)
>

I've attached a forward port of this patch for HEAD.
This also fixes bug #28113.

Hopefully I didn't screw anything up.

/Magnus


-- 
In California they don't throw their garbage away -- they make it into
television shows.
		-- Woody Allen, "Annie Hall"

---

## #10586 — Joe Orton — 2004-06-18T12:24:11+00:00

URL: https://externals.io/message/10583#10586 · In reply to: #10585

> Hi!
> 
> 
> > […]
> 
> I've attached a forward port of this patch for HEAD.
> This also fixes bug #28113.

Ah, thanks Magnus.  Note that `flush()` may still leak a small amount of
memory but this is what I'm working to fix in httpd.

Regards,

joe
