Bug #66370 [Opn]: Errors in mysqli_store_result() do not set mysqli error/errno

From: Date: Tue, 24 Oct 2017 14:59:28 +0000
Subject: Bug #66370 [Opn]: Errors in mysqli_store_result() do not set mysqli error/errno
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-212282@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=66370&edit=1

 ID:                 66370
 User updated by:    bugs dot php dot net at ss dot chernousov dot net
 Reported by:        bugs dot php dot net at ss dot chernousov dot net
-Summary:            Errors in mysqli_store_result() don't not set mysqli
                     error/errno
+Summary:            Errors in mysqli_store_result() do not set mysqli
                     error/errno
 Status:             Open
 Type:               Bug
 Package:            MySQLi related
 Operating System:   Gentoo Linux
 PHP Version:        5.5.7
 Block user comment: N
 Private report:     N

 New Comment:

(fixed summary title)


Previous Comments:
------------------------------------------------------------------------
[2016-08-04 11:31:14] sergey at dotsgo dot com

Just stuck with the same issue while dealing with a mysql server on another continent and
transferring large amounts of data on an unreliable connection.

------------------------------------------------------------------------
[2013-12-31 03:23:52] bugs dot php dot net at ss dot chernousov dot net

Description:
------------
(This is related to mysqlnd in general, not only to mysqli).

When connection gets broken while store_result()/query() is transferring data, "Empty row
packet body" warning is generated, but errno/error are not set. Any following
mysql-network-related function generates 2006/"MySQL server has gone away" and correctly
sets errno/error. Expected behaviour: store_result()/query() to set errno/error immediately after an
error happened.


More digging details below.

store_result() generates one Warning ("Empty row packet body"), but query() generates two:

Warning: Empty row packet body in 1.php on line 5
Warning: mysqli::query(): (00000/0):  in 1.php on line 5

And neither of them sets errno/error.

I added CONN_SET_STATE(conn, CONN_QUIT_SENT) and SET_CLIENT_ERROR(*conn->error_info, ...) to
php_mysqlnd_read_row_ex() in mysqlnd_wireprotocol.c (similarly to PACKET_READ_HEADER_AND_BODY
macro), and found another problem: errors from mysqlnd_wireprotocol.c are set to
*conn->error_info, but store_result_fetch_data() in mysqlnd_result.c expects errors in
row_packet->error_info. It seems that errors generated in mysqlnd_wireprotocol.c are never
actually used in mysqlnd_result.c. Furthermore, connection state set in mysqlnd_wireprotocol.c is
always overwritten in mysqlnd_result.c with either CONN_NEXT_RESULT_PENDING or CONN_READY.

I ended up with the following patch to at least set correct errno/error on store_result()/query(),
so the script can get aware about lost connections timely. However this patch is definitely not a
complete solution, it doesn't fix neither double warning nor connection state (and it looks
like it's not the only place where warnings are raised but errno/error are not set).

Test script:
---------------
<?php

// connect to a remote server, slow connection is preferrable (so you'll have more time to kill
the connection)
// while script is performing $mysqli->query(), kill the connection using mysql "kill"
command (killall -9 mysqld would work too :))

$mysqli = new mysqli('remote-host', 'user', 'password');
$mysqli->query('set global max_allowed_packet=' . 60e6); // 60M
// echo "Do this in mysql shell: kill {$mysqli->threadid}\n";
$mysqli->query('select
repeat("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
500000)'); // ~50M packet
echo "errno={$mysqli->errno}, error={$mysqli->error}\n";

Expected result:
----------------
Warning: mysqli::query(): (HY000/2006): MySQL server has gone away in 1.php on line 9
errno=2006, error=MySQL server has gone away

Actual result:
--------------
Warning: Empty row packet body in 1.php on line 9
Warning: mysqli::query(): (00000/0):  in 1.php on line 9
errno=0, error=


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=66370&edit=1


Thread (7 messages)

« previous php.bugs (#212282) next »