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