From b272c1e03de58ff0c01f78421b824c7f45d43959 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 8 Jun 2005 10:01:09 +0000 Subject: [PATCH] - proper request pool cleanup --- http_methods.c | 11 ++++++++++- http_request_api.c | 27 +++++++++++++++++++-------- http_request_object.c | 2 +- http_requestpool_object.c | 16 +++++++++++++--- php_http_request_api.h | 3 +++ php_http_request_object.h | 2 +- php_http_requestpool_object.h | 3 +++ 7 files changed, 50 insertions(+), 14 deletions(-) diff --git a/http_methods.c b/http_methods.c index cf8f25d..053fce7 100644 --- a/http_methods.c +++ b/http_methods.c @@ -2119,7 +2119,7 @@ PHP_METHOD(HttpRequest, send) SET_EH_THROW_HTTP(); - if (obj->attached) { + if (obj->pool) { http_error(E_WARNING, HTTP_E_CURL, "You cannot call HttpRequest::send() while attached to an HttpRequestPool"); RETURN_FALSE; } @@ -2153,6 +2153,15 @@ PHP_METHOD(HttpRequestPool, __construct) } /* }}} */ +PHP_METHOD(HttpRequestPool, __destruct) +{ + getObject(http_requestpool_object, obj); + + NO_ARGS; + + http_requestpool_object_ondestruct(&obj->pool); +} + /* {{{ proto bool HttpRequestPool::attach(HttpRequest request) * * Attach an HttpRequest object to this HttpRequestPool. diff --git a/http_request_api.c b/http_request_api.c index 934bc87..5a90936 100644 --- a/http_request_api.c +++ b/http_request_api.c @@ -124,6 +124,7 @@ typedef struct { static http_curl_callback_ctx *_http_curl_callback_data(void *data TSRMLS_DC); static void http_request_pool_freebody(http_request_body **body); +static void http_request_pool_freehandle(zval **request); static void http_request_pool_responsehandler(zval **req TSRMLS_DC); static inline STATUS http_request_pool_select(http_request_pool *pool); static inline void http_request_pool_perform(http_request_pool *pool); @@ -168,13 +169,13 @@ void *_http_request_data_copy(int type, void *data TSRMLS_DC) zend_llist_add_element(&HTTP_G(request).copies.strings, &new_str); return new_str; } - + case COPY_SLIST: { zend_llist_add_element(&HTTP_G(request).copies.slists, &data); return data; } - + default: { return data; @@ -831,7 +832,7 @@ PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *req { getObjectEx(http_request_object, req, request); - if (req->attached) { + if (req->pool) { http_error(E_WARNING, HTTP_E_CURL, "HttpRequest object is already member of an HttpRequestPool"); } else { CURLMcode code; @@ -844,7 +845,7 @@ PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *req } else if (CURLM_OK != (code = curl_multi_add_handle(pool->ch, req->ch))) { http_error_ex(E_WARNING, HTTP_E_CURL, "Could not attach HttpRequest object to the HttpRequestPool: %s", curl_multi_strerror(code)); } else { - req->attached = 1; + req->pool = pool; zval_add_ref(&request); zend_llist_add_element(&pool->handles, &request); zend_llist_add_element(&pool->bodies, &body); @@ -860,15 +861,15 @@ PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *req { getObjectEx(http_request_object, req, request); - if (!req->attached) { - http_error(E_WARNING, HTTP_E_CURL, "HttpRequest object is not attached to an HttpRequestPool"); + if (req->pool != pool) { + http_error(E_WARNING, HTTP_E_CURL, "HttpRequest object is not attached to this HttpRequestPool"); } else { CURLMcode code; if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->ch))) { http_error_ex(E_WARNING, HTTP_E_CURL, "Could not detach HttpRequest object from the HttpRequestPool: %s", curl_multi_strerror(code)); } else { - req->attached = 0; + req->pool = NULL; zval_ptr_dtor(&request); return SUCCESS; } @@ -893,9 +894,19 @@ PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool TSRMLS_DC) } /* }}} */ +/* {{{ void http_request_pool_dtor(http_request_pool *) */ +PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool TSRMLS_DC) +{ + pool->unfinished = 0; + zend_llist_clean(&pool->handles); + zend_llist_clean(&pool->bodies); + curl_multi_cleanup(pool->ch); +} +/* }}} */ + /*#*/ -/* {{{ static void http_request_pool_free_body(http_request_body *) */ +/* {{{ static void http_request_pool_freebody(http_request_body **) */ static void http_request_pool_freebody(http_request_body **body) { TSRMLS_FETCH(); diff --git a/http_request_object.c b/http_request_object.c index 1cc8df5..055a43e 100644 --- a/http_request_object.c +++ b/http_request_object.c @@ -156,7 +156,7 @@ zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC) o = ecalloc(1, sizeof(http_request_object)); o->zo.ce = ce; o->ch = curl_easy_init(); - o->attached = 0; + o->pool = NULL; phpstr_init_ex(&o->response, HTTP_CURLBUF_SIZE, 0); diff --git a/http_requestpool_object.c b/http_requestpool_object.c index 09fc261..a683b05 100644 --- a/http_requestpool_object.c +++ b/http_requestpool_object.c @@ -42,6 +42,7 @@ static inline void _http_requestpool_object_declare_default_properties(TSRMLS_D) zend_class_entry *http_requestpool_object_ce; zend_function_entry http_requestpool_object_fe[] = { PHP_ME(HttpRequestPool, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) + PHP_ME(HttpRequestPool, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) PHP_ME(HttpRequestPool, attach, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpRequestPool, detach, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpRequestPool, send, NULL, ZEND_ACC_PUBLIC) @@ -90,12 +91,21 @@ void _http_requestpool_object_free(zend_object *object TSRMLS_DC) zend_hash_destroy(OBJ_PROP(o)); FREE_HASHTABLE(OBJ_PROP(o)); } - if (o->pool.ch) { - curl_multi_cleanup(o->pool.ch); - } + http_request_pool_dtor(&o->pool); efree(o); } +static void http_requestpool_object_ondestructhandler(zval **request, http_request_pool *pool TSRMLS_DC) +{ + http_request_pool_detach(pool, *request); +} + +void _http_requestpool_object_ondestruct(http_request_pool *pool TSRMLS_DC) +{ + zend_llist_apply_with_argument(&pool->handles, (llist_apply_with_arg_func_t) http_requestpool_object_ondestructhandler, pool TSRMLS_CC); +} + + #endif /* HTTP_HAVE_CURL */ #endif /* ZEND_ENGINE_2 */ diff --git a/php_http_request_api.h b/php_http_request_api.h index df335bf..52897b6 100644 --- a/php_http_request_api.h +++ b/php_http_request_api.h @@ -131,6 +131,9 @@ PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *req #define http_request_pool_send(p) _http_request_pool_send((p) TSRMLS_CC) PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool TSRMLS_DC); +#define http_request_pool_dtor(p) _http_request_pool_dtor((p) TSRMLS_CC) +PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool TSRMLS_DC); + #define http_request_init(ch, meth, url, body, options, response) _http_request_init((ch), (meth), (url), (body), (options), (response) TSRMLS_CC) PHP_HTTP_API STATUS _http_request_init(CURL *ch, http_request_method meth, const char *url, http_request_body *body, HashTable *options, phpstr *response TSRMLS_DC); diff --git a/php_http_request_object.h b/php_http_request_object.h index e8326b3..e223785 100644 --- a/php_http_request_object.h +++ b/php_http_request_object.h @@ -32,7 +32,7 @@ typedef struct { zend_object zo; CURL *ch; - zend_bool attached; + http_request_pool *pool; phpstr response; } http_request_object; diff --git a/php_http_requestpool_object.h b/php_http_requestpool_object.h index 1981c85..1ee1a9e 100644 --- a/php_http_requestpool_object.h +++ b/php_http_requestpool_object.h @@ -42,8 +42,11 @@ extern void _http_requestpool_object_init(INIT_FUNC_ARGS); extern zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC); #define http_requestpool_object_free _http_requestpool_object_free extern void _http_requestpool_object_free(zend_object *object TSRMLS_DC); +#define http_requestpool_object_ondestruct(p) _http_requestpool_object_ondestruct((p) TSRMLS_CC) +extern void _http_requestpool_object_ondestruct(http_request_pool *pool TSRMLS_DC); PHP_METHOD(HttpRequestPool, __construct); +PHP_METHOD(HttpRequestPool, __destruct); PHP_METHOD(HttpRequestPool, attach); PHP_METHOD(HttpRequestPool, detach); PHP_METHOD(HttpRequestPool, send); -- 2.30.2