]> granicus.if.org Git - php/commitdiff
Suppress stream errors in mysqlnd
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 26 Nov 2020 11:30:17 +0000 (12:30 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 30 Nov 2020 14:06:28 +0000 (15:06 +0100)
mysqlnd currently sets error_reporting=0 to suppress errors while
writing to streams. Unfortunately these errors are still visible
to userland error handlers, which is a source of confusion.
See for example https://bugs.php.net/bug.php?id=80412.

Instead add a stream flag that suppresses the emission of
read/write errors in the first place, and set it in mysqlnd.

I think it might be useful to have this option for userland as
well in the future, but for now this is just an internal
mechanism.

Closes GH-6458.

ext/mysqlnd/mysqlnd_vio.c
ext/mysqlnd/mysqlnd_wireprotocol.c
main/php_streams.h
main/streams/plain_wrapper.c
main/streams/xp_socket.c

index bc59cbeed845e26366cc200776c12c56999538ca..e33761f278251ddd65407d658fb12831939d1d15 100644 (file)
@@ -263,6 +263,7 @@ MYSQLND_METHOD(mysqlnd_vio, post_connect_set_opt)(MYSQLND_VIO * const vio, const
                }
 
                net_stream->chunk_size = vio->data->options.net_read_buffer_size;
+               net_stream->flags |= PHP_STREAM_FLAG_SUPPRESS_ERRORS;
        }
 
        DBG_VOID_RETURN;
index e11d42d8bd6f8bd157c40b5b8350b6cdb21a8256..33a000d9a6b20fe491491950c80a5f8f6e3d231d 100644 (file)
@@ -971,7 +971,6 @@ size_t php_mysqlnd_cmd_write(MYSQLND_CONN_DATA * conn, void * _packet)
        MYSQLND_VIO * vio = conn->vio;
        MYSQLND_STATS * stats = conn->stats;
        MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
-       const unsigned int error_reporting = EG(error_reporting);
        size_t sent = 0;
 
        DBG_ENTER("php_mysqlnd_cmd_write");
@@ -981,10 +980,6 @@ size_t php_mysqlnd_cmd_write(MYSQLND_CONN_DATA * conn, void * _packet)
        */
        pfc->data->m.reset(pfc, stats, error_info);
 
-       if (error_reporting) {
-               EG(error_reporting) = 0;
-       }
-
        MYSQLND_INC_CONN_STATISTIC(stats, STAT_PACKETS_SENT_CMD);
 
 #ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
@@ -1017,10 +1012,6 @@ size_t php_mysqlnd_cmd_write(MYSQLND_CONN_DATA * conn, void * _packet)
                }
        }
 end:
-       if (error_reporting) {
-               /* restore error reporting */
-               EG(error_reporting) = error_reporting;
-       }
        if (!sent) {
                SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
        }
index 73740a7a7907c101f2811bf24c3715c8747d1aa6..6d6c73bb9570687fb7d1ae81e858b5100ad43b0f 100644 (file)
@@ -181,6 +181,10 @@ struct _php_stream_wrapper {
 
 #define PHP_STREAM_FLAG_NO_FCLOSE                                      0x80
 
+/* Suppress generation of PHP warnings on stream read/write errors.
+ * Currently for internal use only. */
+#define PHP_STREAM_FLAG_SUPPRESS_ERRORS                                0x100
+
 #define PHP_STREAM_FLAG_WAS_WRITTEN                                    0x80000000
 
 struct _php_stream  {
index 8a891ddf720ad6ae0cf324019dae11ad1c862e0a..e3eda978d87bda7dd56a386a0d80152794d81a5c 100644 (file)
@@ -358,7 +358,9 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
                                /* TODO: Should this be treated as a proper error or not? */
                                return bytes_written;
                        }
-                       php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
+                       if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
+                               php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
+                       }
                }
                return bytes_written;
        } else {
@@ -426,7 +428,9 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
                        } else if (errno == EINTR) {
                                /* TODO: Should this be treated as a proper error or not? */
                        } else {
-                               php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
+                               if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
+                                       php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
+                               }
 
                                /* TODO: Remove this special-case? */
                                if (errno != EBADF) {
index f3370e89f7e69dea5256f8fa57ddf66148aacf8e..a369bf5ff2d8c2ab413cea468619992ccb4f4c43 100644 (file)
@@ -103,10 +103,13 @@ retry:
                        }
                }
 
-               estr = php_socket_strerror(err, NULL, 0);
-               php_error_docref(NULL, E_NOTICE, "Send of " ZEND_LONG_FMT " bytes failed with errno=%d %s",
+               if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
+                       estr = php_socket_strerror(err, NULL, 0);
+                       php_error_docref(NULL, E_NOTICE,
+                               "Send of " ZEND_LONG_FMT " bytes failed with errno=%d %s",
                                (zend_long)count, err, estr);
-               efree(estr);
+                       efree(estr);
+               }
        }
 
        if (didwrite > 0) {