|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
Patchesmysqlnd-errno-error-fix.patch (last revision 2013-12-31 03:24 UTC by bugs dot php dot net at ss dot chernousov dot net)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
[2014-02-17 11:47 UTC] andrey@php.net
-Status: Open
+Status: Assigned
-Assigned To:
+Assigned To: andrey
[2016-08-04 11:31 UTC] sergey at dotsgo dot com
[2017-10-24 07:21 UTC] kalle@php.net
-Status: Assigned
+Status: Open
-Assigned To: andrey
+Assigned To:
[2017-10-24 14:59 UTC] 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
[2017-10-24 14:59 UTC] bugs dot php dot net at ss dot chernousov dot net
[2020-10-29 09:42 UTC] nikic@php.net
[2020-10-29 10:01 UTC] nikic@php.net
-Status: Open
+Status: Closed
-Assigned To:
+Assigned To: nikic
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 20:00:01 2025 UTC |
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=