summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2010-05-03 17:07:18 +0000
committerAndrey Hristov <andrey@php.net>2010-05-03 17:07:18 +0000
commit6dff9e55be3446333f9c25a3acc29ca8017971ad (patch)
tree5e97fc1def97f75e15e56addb393c62e1a4e05dc
parent44bcdeeb772d17e8d81224a6d78c5fbf1718419e (diff)
downloadphp-git-6dff9e55be3446333f9c25a3acc29ca8017971ad.tar.gz
Handle gracefully OOM in mysqlnd_mempool_create and up the stack
-rw-r--r--ext/mysqlnd/mysqlnd.c20
-rw-r--r--ext/mysqlnd/mysqlnd_block_alloc.c18
-rw-r--r--ext/mysqlnd/mysqlnd_result.c42
3 files changed, 51 insertions, 29 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index 414d6f2b5a..f67c468c83 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -2060,7 +2060,7 @@ oom:
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_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);
- result = conn->current_result;
- conn->current_result = NULL;
- result->conn = conn->m->get_reference(conn TSRMLS_CC);
+ conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
+ result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
- result = result->m.use_result(result, FALSE TSRMLS_CC);
+ if (!result) {
+ conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ }
+ conn->current_result = NULL;
+
DBG_RETURN(result);
}
/* }}} */
@@ -2112,10 +2115,11 @@ MYSQLND_METHOD(mysqlnd_conn, store_result)(MYSQLND * const conn TSRMLS_DC)
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);
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_block_alloc.c b/ext/mysqlnd/mysqlnd_block_alloc.c
index 5d618d145e..8bcfffa951 100644
--- a/ext/mysqlnd/mysqlnd_block_alloc.c
+++ b/ext/mysqlnd/mysqlnd_block_alloc.c
@@ -156,13 +156,17 @@ mysqlnd_mempool_create(size_t arena_size TSRMLS_DC)
/* 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);
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 657fa40699..5d5ad5012e 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -841,22 +841,28 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
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->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
result->m.row_decoder = php_mysqlnd_rowp_read_text_protocol;
+ result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
+ 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->lengths = NULL;
result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
+ result->lengths = NULL;
}
- 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
@@ -865,6 +871,9 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
*/
/* 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 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
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 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
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 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
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);
}