Bug #70505 [Opn]: mysqli_poll documentation leads to apparent violation of timeout
| From: | bishop@php.net | Date: | Tue, 15 Sep 2015 16:27:56 +0000 |
| Subject: | Bug #70505 [Opn]: mysqli_poll documentation leads to apparent violation of timeout | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-12756@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=70505&edit=1
ID: 70505
Updated by: bishop@php.net
Reported by: bishop@php.net
-Summary: mysqli_poll does not honor timeout when multiple
queries given
+Summary: mysqli_poll documentation leads to apparent
violation of timeout
Status: Open
Type: Bug
-Package: MySQLi related
+Package: Documentation problem
Operating System: any? or 3.14.27-25.47.amzn1.x86_
PHP Version: 5.6.13
Block user comment: N
Private report: N
New Comment:
The documentation for mysqli_poll suggests iterating through the links after running the poll:
foreach ($links as $link) {
if ($result = $link->reap_async_query()) {
print_r($result->fetch_row());
if (is_object($result))
mysqli_free_result($result);
} else die(sprintf("MySQLi Error: %s", mysqli_error($link)));
$processed++;
}
This is not a good way to go about it when you have queries of different run-times, because
mysqli_reap_async_query() blocks until the query resolves, which is contrary to the nature of the
async poll.
An approach that respects multiple queries of different run times is to run a reaping function over
each of the modified arrays:
$count = mysqli_poll($read, $error, $reject, 1);
if (0 < $count) {
array_walk($read, 'reap');
array_walk($error, 'reap');
array_walk($reject, 'reap');
}
function reap($link) {
$result = mysqli_reap_async_query($link);
if (is_object($result)) {
print_r($result->fetch_assoc()));
mysqli_free_result($result);
} else if (false !== $result) {
print_r($link);
} else {
die(mysqli_error($link));
}
}
This also handles the case where the query is a CRUD and the result of reap_async_query isn't a
result object.
Previous Comments:
------------------------------------------------------------------------
[2015-09-15 15:15:30] bishop@php.net
Description:
------------
When mysqli_poll is given a single link in its read array, and the async query on that link runs
longer than the timeout, the timeout expires and poll returns (correctly) that nothing is ready to
read.
However, in the same scenario when there are multiple links to read, mysqli_poll ignores the timeout
and returns only when the longest running query resolves.
The man page is light on this function, so maybe I am misunderstanding how timeout should work.
Also, there's further discussion at this SO post: http://stackoverflow.com/a/32576278/2908724
Test script:
---------------
$link0 = mysqli_connect(...);
$link1 = mysqli_connect(...);
$link2 = mysqli_connect(...);
$sql0 = 'SELECT SLEEP(2) AS wait, 1 AS num';
$sql1 = 'SELECT foo FROM';
$sql2 = 'SELECT 2 AS num';
mysqli_query($link0, $sql0, MYSQLI_ASYNC);
mysqli_query($link1, $sql1, MYSQLI_ASYNC);
mysqli_query($link2, $sql2, MYSQLI_ASYNC);
$links = array ($link0, $link1, $link2);
$begin = microtime(true);
$i = 0;
do {
printf("start i=%d @ T+%.f\n", $i, (microtime(true)-$begin));
$read = $error = $reject = $links;
$count = mysqli_poll($read, $error, $reject, 1, 500000);
if (0 < $count) {
foreach ($links as $j => $link) {
$result = mysqli_reap_async_query($link);
if (is_object($result)) {
printf("link #%d, row=%s\n", $j, json_encode($result->fetch_assoc()));
mysqli_free_result($result);
} else if (false !== $result) {
printf("link #%d, output=%s\n", $j, $link);
} else {
printf("link #%d, error=%s\n", $j, mysqli_error($link));
}
}
}
printf(
"finish i=%d, count(read, error, reject)=(%d, %d, %d) @ T+%f\n\n",
$i++, count($read), count($error), count($reject), (microtime(true)-$begin)
);
} while (count($links) !== count($read) + count($error) + count($reject));
Expected result:
----------------
start i=0 @ T+0.000000
link #0, row=null
link #1, error=You have an error in your SQL syntax; check the manual that corresponds to your MySQL
server version for the right syntax to use near '' at line 1
link #2, row={"num":"2"}
finish i=0, count(read, error, reject)=(1, 1, 0) @ T+1.500000
start i=1 @ T+1.500000
link #0, row={"wait":"0",a"num":"2"}
link #1, row=null
link #2, row=null
finish i=0, count(read, error, reject)=(1, 0, 2) @ T+2.000000
Actual result:
--------------
start i=0 @ T+0.000002
link #0, row={"wait":"0","num":"1"}
link #1, error=You have an error in your SQL syntax; check the manual that corresponds to your MySQL
server version for the right syntax to use near '' at line 1
link #2, row={"num":"2"}
finish i=0, count(read, error, reject)=(1, 0, 0) @ T+2.001756
start i=1 @ T+2.001827
finish i=1, count(read, error, reject)=(0, 0, 3) @ T+3.503024
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=70505&edit=1