Even with ob_flush() and flush(), PHP may be unable to detect the connection status change due to *a firewall on client's machine*.
Consider a browser receiving the output of a script. The script regularly outputs something innocent, like "<br>".
a) The Stop button is pressed. The browser instructs to close the connection gracefully, TCP/IP stack exchanges those final FIN and ACK packets, and the server knows that the client went away.
b) The entire browser is killed. The client's stack sees that nobody is using the socket, so the next data packet from server will be answered with a TCP RST, and the server immediately knows there is no client.
But, a stealth firewall is designed to block those RST messages as well. The server's stack will only see absence of ACK replies, and therefore will occasionally retransmit the entire bunch of accumulated data. Only after a certain number of retransmission failures, this will be considered a connection loss and propagated up to PHP.
In my case, turning off the Comodo Firewall at the client changed the situation immediately.