mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-25 15:03:03 +00:00
BUG/MEDIUM: stream-interface: fix possible stalls during transfers
Sander Klein reported a rare case of POST transfers being stalled after a few megabytes since dev15. One possible culprit is the fix for the CPU spinning issues which is not totally correct, because stream_int_chk_snd_conn() would inconditionally enable the CO_FL_CURR_WR_ENA flag. What could theorically happen is the following sequence : 1) send buffer is empty, server-side polling is disabled 2) client sends some data 3) such data are forwarded to the server using stream_int_chk_snd_conn() 4) conn->flags |= CO_FL_CURR_WR_ENA 5) si_conn_send_loop() is called 6) raw_sock_from_buf() does a partial write due to full kernel buffers 7) stream_int_chk_snd_conn() detects this and requests to be called to send the remaining data using __conn_data_want_send(), and clears the SI_FL_WAIT_DATA flag on the stream interface, indicating that it is already congestionned. 8) conn_cond_update_polling() calls conn_data_update_polling() which sees that both CO_FL_DATA_WR_ENA and CO_FL_CURR_WR_ENA are set, so it does not enable polling on the output fd. 9) the next chunk from the client fills the buffer 10) stream_int_chk_snd_conn() is called again 11) SI_FL_WAIT_DATA is already cleared, so the function immediately returns without doing anything. 12) the buffer is now full with the FD write polling disabled and everything deadlocks. Not that there is no reason for such an issue not to happen the other way around, from server to client, except maybe that due to the speed difference between the client and the server, client-side polling is always enabled and the buffer is never empty. All this shows that the new polling still looks fragile, in part due to the double information on the FD status, being both in fdtab[] and in the connection, which looks unavoidable. We should probably have some functions to tighten the relation between such flags and avoid manipulating them by hand. Also, the effects of chk_snd() on the polling are still under-estimated, while the relation between the stream_int and the FD is still too much present. Maybe the function should be rethought to only call the connection's fd handler. The connection model probably needs two calling conventions for bottom half and upper half.
This commit is contained in:
parent
1c64686788
commit
ca00fbcb91
@ -806,7 +806,8 @@ static void stream_int_chk_snd_conn(struct stream_interface *si)
|
||||
if (si->conn->ctrl)
|
||||
fd_want_send(si->conn->t.sock.fd);
|
||||
si->conn->flags &= ~(CO_FL_WAIT_DATA|CO_FL_WAIT_ROOM|CO_FL_WAIT_RD|CO_FL_WAIT_WR);
|
||||
si->conn->flags |= CO_FL_CURR_WR_ENA;
|
||||
if (fd_ev_is_set(si->conn->t.sock.fd, DIR_WR))
|
||||
si->conn->flags |= CO_FL_CURR_WR_ENA;
|
||||
|
||||
if (si_conn_send_loop(si->conn) < 0) {
|
||||
/* Write error on the file descriptor */
|
||||
|
Loading…
Reference in New Issue
Block a user