I started using push in HTML5 using the JavaScript EventSource object. I was totally happy with a working solution in PHP:
$time = 0;
while(true) {
if(connection_status() != CONNECTION_NORMAL) {
mysql_close()
break;
}
$result = mysql_query("SELECT `id` FROM `table` WHERE UNIX_TIMESTAMP(`lastUpdate`) > '".$time."'");
while($row = mysql_fetch_array($result)) {
echo "data:".$row["id"].PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$time = time();
sleep(1);
}
But suddenly my WebApp wasn’t reachable anymore with an MySQL error “too many connections”.
It turned out that the MySQL connection doesn’t close after closing the event source in JavaScript:
window.onload = function() {
sse = new EventSource("push.php");
sse.onmessage = function(event) {
console.log(event.data.split(":")[1]);
}
}
window.onbeforeunload = function() {
sse.close();
}
So I guess that the PHP script does not stop to execute. Is there any way to call in function (like die();) before the clients connection disconnects? Why doesn’t my script terminate after calling .close(); on the EventSource?!
Thanks for help! —
First off: when you wrap your code in a huge
while(true)loop, your script will never terminate. The connection with the DB would have been closed when your script “ran out of code to execute”, but since you’ve written a deadlock, that’s not going to happen… ever.It’s not an
EventSourceissue, that merely does what it’s supposed to do. It honestly, truly, and sadly is your fault.The thing is: a user connects to your site, and the
EventSourceobject is instantiated. A connection to the server is established and a request for the return value ofpush.phpis requested. Your server does as requested, and runs the script, that -again- is nothing but a deadlock. There are no errors, so it can just keep on running, for as long as the php.ini allows it to run. The.close()method does cancel the stream of output (or rather it should), but your script is so busy either performing its infinite loop, or sleeping. Assuming the script to be stopped because a client disconnects is like assuming that any client could interfere with what the server does. Security-wise this would be the worst that could happen. Now, to answer your actual question: What causes the issue, how to fix it?The answer: HEADERS
Look at this little PHP example: the script isn’t kept alive server-side (by infinite loops), but by setting the correct headers.
Just as a side-note: Please, ditch
mysql_*ASAP, it’s being deprecated (finally), usePDOormysqli_*istead. It’s not that hard, honestly.