How to handle error in sapi

php.internals

Zheng Shao

9 years ago
Hi, I'm working on fix this bug (https://bugs.php.net/bug.php?id=61471) both on PHP-7 and PHP-5.6. The problem is `ap_get_brigade` will return an error when connection timeout happened. in `sapi/apache2handler/sapi_apache2.c`: static int php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) { apr_size_t len, tlen=0; php_struct *ctx = SG(server_context); request_rec *r; apr_bucket_brigade *brigade; + apr_status_t ret; + int error; r = ctx->r; brigade = ctx->brigade; len = count_bytes; /* * This loop is needed because ap_get_brigade() can return us partial data * which would cause premature termination of request read. Therefor we * need to make sure that if data is available we fill the buffer completely. */ - while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) { + while ((ret=ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len)) == APR_SUCCESS) { apr_brigade_flatten(brigade, buf, &len); apr_brigade_cleanup(brigade); tlen += len; if (tlen == count_bytes || !len) { break; } buf += len; len = count_bytes - tlen; } + if (ret != APR_SUCCESS){ + if (APR_STATUS_IS_TIMEUP(ret)) { + error = ap_map_http_request_error(ret, HTTP_REQUEST_TIME_OUT); + } else { + error = ap_map_http_request_error(ret, HTTP_BAD_REQUEST); + } + // HOW TO HANDLE ERROR HERE, should I throw a zend_throw_exception? + // zend_throw_exception(NULL, "Read POST data error", error); + } return tlen; } @@ -616,6 +625,7 @@ zend_first_try { ctx->brigade = brigade; if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) { + // HANDLE zend_throw_exception TIMEOUT HERE ? zend_bailout(); } } else { @@ -627,6 +637,7 @@ zend_first_try { strcmp(parent_req->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(parent_req->handler, PHP_SCRIPT)) { if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) { + // HANDLE zend_throw_exception TIMEOUT HERE ? zend_bailout(); } } I'm confused by how to handle an error inside php_apache_sapi_read_post, shoud I throw a zend_throw_exception or use a global flag for error handling? Thank you
-- Zheng SHAO axot@axot.org

Kalle Sommer Nielsen

9 years ago
Hi Zheng 2016-11-25 6:40 GMT+01:00 Zheng Shao <axot@axot.org>:
> I'm confused by how to handle an error inside php_apache_sapi_read_post, shoud I throw a zend_throw_exception or use a global flag for error handling?
php_apache_sapi_read_post() is invoked very early on (php_module_startup > sapi_activate > sapi_read_post_data), and therefore we are too early at initialization that you cannot really throw an exception to the user. What you can do however is to call php_apache_sapi_log_message() and try to log the error in the Apache error log instead, which seems more reasonable to me.
-- regards, Kalle Sommer Nielsen kalle@php.net

Zheng Shao

9 years ago
> php_apache_sapi_read_post() is invoked very early on > (php_module_startup > sapi_activate > sapi_read_post_data), and > therefore we are too early at initialization that you cannot really > throw an exception to the user. What you can do however is to call > php_apache_sapi_log_message() and try to log the error in the Apache > error log instead, which seems more reasonable to me.
When timeout happened in POST data reading, `php_handler` function should return 408 error to Apache. For now, it will ignore the error and execute PHP Code then return 200 to Apache. What can we do to handle the error in this case? Regards,
-- Zheng SHAO axot@axot.org

Zheng Shao

9 years ago
Hi apache2handler maintainers, I pushed a commit to fix #61471 in https://github.com/php/php-src/pull/2180 . Could you have time to take a look? Thank you
-- Zheng SHAO