summaryrefslogtreecommitdiff
path: root/ext/mysqlnd/mysqlnd_vio.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-07-18 15:25:59 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-07-22 17:17:28 +0200
commitd59aac58b3e7da7ad01a194fe9840d89725ea229 (patch)
tree5cfc4509f8aa6f9cb0c49df3530fb82c5b0456df /ext/mysqlnd/mysqlnd_vio.c
parentc817b8020c8a835946681ca94b9257e78e64dad3 (diff)
downloadphp-git-d59aac58b3e7da7ad01a194fe9840d89725ea229.tar.gz
Report errors from stream read and write operations
The php_stream_read() and php_stream_write() functions now return an ssize_t value, with negative results indicating failure. Functions like fread() and fwrite() will return false in that case. As a special case, EWOULDBLOCK and EAGAIN on non-blocking streams should not be regarded as error conditions, and be reported as successful zero-length reads/writes instead. The handling of EINTR remains unclear and is internally inconsistent (e.g. some code-paths will automatically retry on EINTR, while some won't). I'm landing this now to make sure the stream wrapper ops API changes make it into 7.4 -- however, if the user-facing changes turn out to be problematic we have the option of clamping negative returns to zero in php_stream_read() and php_stream_write() to restore the old behavior in a relatively non-intrusive manner.
Diffstat (limited to 'ext/mysqlnd/mysqlnd_vio.c')
-rw-r--r--ext/mysqlnd/mysqlnd_vio.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/ext/mysqlnd/mysqlnd_vio.c b/ext/mysqlnd/mysqlnd_vio.c
index 99c41f0fe7..a5685e6707 100644
--- a/ext/mysqlnd/mysqlnd_vio.c
+++ b/ext/mysqlnd/mysqlnd_vio.c
@@ -79,14 +79,15 @@ MYSQLND_METHOD(mysqlnd_vio, network_read)(MYSQLND_VIO * const vio, zend_uchar *
{
enum_func_status return_value = PASS;
php_stream * net_stream = vio->data->m.get_stream(vio);
- size_t to_read = count, ret;
+ size_t to_read = count;
zend_uchar * p = buffer;
DBG_ENTER("mysqlnd_vio::network_read");
DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count);
while (to_read) {
- if (!(ret = php_stream_read(net_stream, (char *) p, to_read))) {
+ ssize_t ret = php_stream_read(net_stream, (char *) p, to_read);
+ if (ret <= 0) {
DBG_ERR_FMT("Error while reading header from socket");
return_value = FAIL;
break;
@@ -101,11 +102,11 @@ MYSQLND_METHOD(mysqlnd_vio, network_read)(MYSQLND_VIO * const vio, zend_uchar *
/* {{{ mysqlnd_vio::network_write */
-static size_t
+static ssize_t
MYSQLND_METHOD(mysqlnd_vio, network_write)(MYSQLND_VIO * const vio, const zend_uchar * const buffer, const size_t count,
MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
{
- size_t ret;
+ ssize_t ret;
DBG_ENTER("mysqlnd_vio::network_write");
DBG_INF_FMT("sending %u bytes", count);
ret = php_stream_write(vio->data->m.get_stream(vio), (char *)buffer, count);
@@ -451,10 +452,14 @@ MYSQLND_METHOD(mysqlnd_vio, consume_uneaten_data)(MYSQLND_VIO * const net, enum
if (PHP_STREAM_OPTION_RETURN_ERR != was_blocked) {
/* Do a read of 1 byte */
- int bytes_consumed;
+ ssize_t bytes_consumed;
do {
- skipped_bytes += (bytes_consumed = php_stream_read(net_stream, tmp_buf, sizeof(tmp_buf)));
+ bytes_consumed = php_stream_read(net_stream, tmp_buf, sizeof(tmp_buf));
+ if (bytes_consumed <= 0) {
+ break;
+ }
+ skipped_bytes += bytes_consumed;
} while (bytes_consumed == sizeof(tmp_buf));
if (was_blocked) {