andrey                                   Mon, 03 May 2010 17:07:18 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=298917

Log:
Handle gracefully OOM in mysqlnd_mempool_create and up the stack

Changed paths:
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_block_alloc.c
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c	2010-05-03 16:48:18 UTC (rev 298916)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c	2010-05-03 17:07:18 UTC (rev 298917)
@@ -2060,7 +2060,7 @@
 static MYSQLND_RES *
 MYSQLND_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
 {
-	MYSQLND_RES *result;
+	MYSQLND_RES * result;

 	DBG_ENTER("mysqlnd_conn::use_result");
 	DBG_INF_FMT("conn=%llu", conn->thread_id);
@@ -2079,11 +2079,14 @@

 	MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);

-	result = conn->current_result;
+	conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
+	result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
+
+	if (!result) {
+		conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+	}
 	conn->current_result = NULL;
-	result->conn = conn->m->get_reference(conn TSRMLS_CC);
-
-	result = result->m.use_result(result, FALSE TSRMLS_CC);
+
 	DBG_RETURN(result);
 }
 /* }}} */
@@ -2112,10 +2115,11 @@

 	MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);

-	result = conn->current_result;
+	result = conn->current_result->m.store_result(conn->current_result, conn, FALSE TSRMLS_CC);
+	if (!result) {
+		conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+	}
 	conn->current_result = NULL;
-
-	result = result->m.store_result(result, conn, FALSE TSRMLS_CC);
 	DBG_RETURN(result);
 }
 /* }}} */

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_block_alloc.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_block_alloc.c	2010-05-03 16:48:18 UTC (rev 298916)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_block_alloc.c	2010-05-03 17:07:18 UTC (rev 298917)
@@ -156,13 +156,17 @@
 	/* We calloc, because we free(). We don't mnd_calloc()  for a reason. */
 	MYSQLND_MEMORY_POOL * ret = mnd_calloc(1, sizeof(MYSQLND_MEMORY_POOL));
 	DBG_ENTER("mysqlnd_mempool_create");
-
-	ret->free_size = ret->arena_size = arena_size ? arena_size : 0;
-	ret->refcount = 0;
-	/* OOM ? */
-	ret->arena = mnd_malloc(ret->arena_size);
-	ret->get_chunk = mysqlnd_mempool_get_chunk;
-
+	if (ret) {
+		ret->get_chunk = mysqlnd_mempool_get_chunk;
+		ret->free_size = ret->arena_size = arena_size ? arena_size : 0;
+		ret->refcount = 0;
+		/* OOM ? */
+		ret->arena = mnd_malloc(ret->arena_size);
+		if (!ret->arena) {
+			mysqlnd_mempool_destroy(ret TSRMLS_CC);
+			ret = NULL;
+		}
+	}
 	DBG_RETURN(ret);
 }
 /* }}} */

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c	2010-05-03 16:48:18 UTC (rev 298916)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c	2010-05-03 17:07:18 UTC (rev 298917)
@@ -841,23 +841,29 @@

 	SET_EMPTY_ERROR(result->conn->error_info);

+	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
+	result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+	if (!result->result_set_memory_pool || !result->unbuf) {
+		goto oom;
+	}
+
 	if (ps == FALSE) {
 		result->type			= MYSQLND_RES_NORMAL;
 		result->m.fetch_row		= result->m.fetch_row_normal_unbuffered;
 		result->m.fetch_lengths	= mysqlnd_fetch_lengths_unbuffered;
+		result->m.row_decoder	= php_mysqlnd_rowp_read_text_protocol;
 		result->lengths			= mnd_ecalloc(result->field_count, sizeof(unsigned long));
-		result->m.row_decoder	= php_mysqlnd_rowp_read_text_protocol;
+		if (!result->lengths) {
+			goto oom;
+		}
 	} else {
 		result->type			= MYSQLND_RES_PS_UNBUF;
 		/* result->m.fetch_row() will be set in mysqlnd_ps.c */
 		result->m.fetch_lengths	= NULL; /* makes no sense */
+		result->m.row_decoder	= php_mysqlnd_rowp_read_binary_protocol;
 		result->lengths 		= NULL;
-		result->m.row_decoder	= php_mysqlnd_rowp_read_binary_protocol;
 	}
-	result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));

-	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
-
 	/*
 	  Will be freed in the mysqlnd_internal_free_result_contents() called
 	  by the resource destructor. mysqlnd_fetch_row_unbuffered() expects
@@ -865,6 +871,9 @@
 	*/
 	/* FALSE = non-persistent */
 	result->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE TSRMLS_CC);
+	if (!result->row_packet) {
+		goto oom;
+	}
 	result->row_packet->result_set_memory_pool = result->result_set_memory_pool;
 	result->row_packet->field_count = result->field_count;
 	result->row_packet->binary_protocol = ps;
@@ -873,6 +882,9 @@
 	result->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len;

 	DBG_RETURN(result);
+oom:
+	SET_OOM_ERROR(result->conn->error_info);
+	DBG_RETURN(NULL);
 }
 /* }}} */

@@ -1163,6 +1175,13 @@
 	DBG_ENTER("mysqlnd_res::store_result");
 	DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps_protocol);

+	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
+	result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
+	if (!result->result_set_memory_pool || !result->lengths) {
+		SET_OOM_ERROR(conn->error_info);
+		DBG_RETURN(NULL);
+	}
+
 	/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
 	result->conn 			= conn->m->get_reference(conn TSRMLS_CC);
 	result->type			= MYSQLND_RES_NORMAL;
@@ -1171,18 +1190,13 @@

 	CONN_SET_STATE(conn, CONN_FETCHING_DATA);

-	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
-	result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
-
 	ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol, to_cache TSRMLS_CC);
-	if (PASS == ret) {
-		/* libmysql's documentation says it should be so for SELECT statements */
-		conn->upsert_status.affected_rows = result->stored_data->row_count;
-	} else {
+	if (FAIL == ret) {
 		conn->error_info = result->stored_data->error_info;
-		result->m.free_result_internal(result TSRMLS_CC);
-		result = NULL;
+		DBG_RETURN(NULL);
 	}
+	/* libmysql's documentation says it should be so for SELECT statements */
+	conn->upsert_status.affected_rows = result->stored_data->row_count;

 	DBG_RETURN(result);
 }

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd.c	2010-05-03 16:48:18 UTC (rev 298916)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd.c	2010-05-03 17:07:18 UTC (rev 298917)
@@ -2060,7 +2060,7 @@
 static MYSQLND_RES *
 MYSQLND_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
 {
-	MYSQLND_RES *result;
+	MYSQLND_RES * result;

 	DBG_ENTER("mysqlnd_conn::use_result");
 	DBG_INF_FMT("conn=%llu", conn->thread_id);
@@ -2079,11 +2079,14 @@

 	MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);

-	result = conn->current_result;
+	conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
+	result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
+
+	if (!result) {
+		conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+	}
 	conn->current_result = NULL;
-	result->conn = conn->m->get_reference(conn TSRMLS_CC);
-
-	result = result->m.use_result(result, FALSE TSRMLS_CC);
+
 	DBG_RETURN(result);
 }
 /* }}} */
@@ -2112,10 +2115,11 @@

 	MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);

-	result = conn->current_result;
+	result = conn->current_result->m.store_result(conn->current_result, conn, FALSE TSRMLS_CC);
+	if (!result) {
+		conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+	}
 	conn->current_result = NULL;
-
-	result = result->m.store_result(result, conn, FALSE TSRMLS_CC);
 	DBG_RETURN(result);
 }
 /* }}} */

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c	2010-05-03 16:48:18 UTC (rev 298916)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c	2010-05-03 17:07:18 UTC (rev 298917)
@@ -156,13 +156,17 @@
 	/* We calloc, because we free(). We don't mnd_calloc()  for a reason. */
 	MYSQLND_MEMORY_POOL * ret = mnd_calloc(1, sizeof(MYSQLND_MEMORY_POOL));
 	DBG_ENTER("mysqlnd_mempool_create");
-
-	ret->free_size = ret->arena_size = arena_size ? arena_size : 0;
-	ret->refcount = 0;
-	/* OOM ? */
-	ret->arena = mnd_malloc(ret->arena_size);
-	ret->get_chunk = mysqlnd_mempool_get_chunk;
-
+	if (ret) {
+		ret->get_chunk = mysqlnd_mempool_get_chunk;
+		ret->free_size = ret->arena_size = arena_size ? arena_size : 0;
+		ret->refcount = 0;
+		/* OOM ? */
+		ret->arena = mnd_malloc(ret->arena_size);
+		if (!ret->arena) {
+			mysqlnd_mempool_destroy(ret TSRMLS_CC);
+			ret = NULL;
+		}
+	}
 	DBG_RETURN(ret);
 }
 /* }}} */

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c	2010-05-03 16:48:18 UTC (rev 298916)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c	2010-05-03 17:07:18 UTC (rev 298917)
@@ -841,23 +841,29 @@

 	SET_EMPTY_ERROR(result->conn->error_info);

+	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
+	result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+	if (!result->result_set_memory_pool || !result->unbuf) {
+		goto oom;
+	}
+
 	if (ps == FALSE) {
 		result->type			= MYSQLND_RES_NORMAL;
 		result->m.fetch_row		= result->m.fetch_row_normal_unbuffered;
 		result->m.fetch_lengths	= mysqlnd_fetch_lengths_unbuffered;
+		result->m.row_decoder	= php_mysqlnd_rowp_read_text_protocol;
 		result->lengths			= mnd_ecalloc(result->field_count, sizeof(unsigned long));
-		result->m.row_decoder	= php_mysqlnd_rowp_read_text_protocol;
+		if (!result->lengths) {
+			goto oom;
+		}
 	} else {
 		result->type			= MYSQLND_RES_PS_UNBUF;
 		/* result->m.fetch_row() will be set in mysqlnd_ps.c */
 		result->m.fetch_lengths	= NULL; /* makes no sense */
+		result->m.row_decoder	= php_mysqlnd_rowp_read_binary_protocol;
 		result->lengths 		= NULL;
-		result->m.row_decoder	= php_mysqlnd_rowp_read_binary_protocol;
 	}
-	result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));

-	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
-
 	/*
 	  Will be freed in the mysqlnd_internal_free_result_contents() called
 	  by the resource destructor. mysqlnd_fetch_row_unbuffered() expects
@@ -865,6 +871,9 @@
 	*/
 	/* FALSE = non-persistent */
 	result->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE TSRMLS_CC);
+	if (!result->row_packet) {
+		goto oom;
+	}
 	result->row_packet->result_set_memory_pool = result->result_set_memory_pool;
 	result->row_packet->field_count = result->field_count;
 	result->row_packet->binary_protocol = ps;
@@ -873,6 +882,9 @@
 	result->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len;

 	DBG_RETURN(result);
+oom:
+	SET_OOM_ERROR(result->conn->error_info);
+	DBG_RETURN(NULL);
 }
 /* }}} */

@@ -1163,6 +1175,13 @@
 	DBG_ENTER("mysqlnd_res::store_result");
 	DBG_INF_FMT("conn=%d ps_protocol=%d", conn->thread_id, ps_protocol);

+	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
+	result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
+	if (!result->result_set_memory_pool || !result->lengths) {
+		SET_OOM_ERROR(conn->error_info);
+		DBG_RETURN(NULL);
+	}
+
 	/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
 	result->conn 			= conn->m->get_reference(conn TSRMLS_CC);
 	result->type			= MYSQLND_RES_NORMAL;
@@ -1171,18 +1190,13 @@

 	CONN_SET_STATE(conn, CONN_FETCHING_DATA);

-	result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
-	result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
-
 	ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol, to_cache TSRMLS_CC);
-	if (PASS == ret) {
-		/* libmysql's documentation says it should be so for SELECT statements */
-		conn->upsert_status.affected_rows = result->stored_data->row_count;
-	} else {
+	if (FAIL == ret) {
 		conn->error_info = result->stored_data->error_info;
-		result->m.free_result_internal(result TSRMLS_CC);
-		result = NULL;
+		DBG_RETURN(NULL);
 	}
+	/* libmysql's documentation says it should be so for SELECT statements */
+	conn->upsert_status.affected_rows = result->stored_data->row_count;

 	DBG_RETURN(result);
 }
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to