mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-28 06:11:32 +01:00
BUG/MEDIUM: stream-int: Don't rely on CF_WRITE_PARTIAL to unblock opposite si
In the function stream_int_notify(), when the opposite stream-interface is blocked because there is no more room into the input buffer, if the flag CF_WRITE_PARTIAL is set on this buffer, it is unblocked. It is a way to unblock the reads on the other side because some data was sent. But it is a problem during the fast-forwarding because only the stream is able to remove the flag CF_WRITE_PARTIAL. So it is possible to have this flag because of a previous send while the input buffer of the opposite stream-interface is now full. In such case, the opposite stream-interface will be woken up for nothing because its input buffer is full. If the same happens on the opposite side, we will have a loop consumming all the CPU. To fix the bug, the opposite side is now only notify if there is some available room in its input buffer in the function si_cs_send(), so only if some data was sent. This patch must be backported to 2.0 and 1.9.
This commit is contained in:
parent
86162db15c
commit
037b3ebd35
@ -950,6 +950,7 @@ static inline void co_skip(struct channel *chn, int len)
|
||||
|
||||
/* notify that some data was written to the SI from the buffer */
|
||||
chn->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
|
||||
chn_prod(chn)->flags &= ~SI_FL_RXBLK_ROOM; // si_rx_room_rdy()
|
||||
}
|
||||
|
||||
/* HTX version of co_skip(). This function skips at most <len> bytes from the
|
||||
@ -967,6 +968,7 @@ static inline void co_htx_skip(struct channel *chn, struct htx *htx, int len)
|
||||
|
||||
/* notify that some data was written to the SI from the buffer */
|
||||
chn->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
|
||||
chn_prod(chn)->flags &= ~SI_FL_RXBLK_ROOM; // si_rx_room_rdy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -482,10 +482,6 @@ static void stream_int_notify(struct stream_interface *si)
|
||||
ic->rex = tick_add_ifset(now_ms, ic->rto);
|
||||
}
|
||||
|
||||
if ((sio->flags & SI_FL_RXBLK_ROOM) &&
|
||||
((oc->flags & CF_WRITE_PARTIAL) || channel_is_empty(oc)))
|
||||
si_rx_room_rdy(sio);
|
||||
|
||||
if (oc->flags & CF_DONT_READ)
|
||||
si_rx_chan_blk(sio);
|
||||
else
|
||||
@ -761,6 +757,8 @@ int si_cs_send(struct conn_stream *cs)
|
||||
oc->flags |= CF_WRITE_PARTIAL | CF_WROTE_DATA;
|
||||
if (si->state == SI_ST_CON)
|
||||
si->state = SI_ST_RDY;
|
||||
|
||||
si_rx_room_rdy(si_opposite(si));
|
||||
}
|
||||
|
||||
if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) {
|
||||
@ -920,8 +918,7 @@ void si_sync_send(struct stream_interface *si)
|
||||
if (cs->conn->flags & CO_FL_ERROR)
|
||||
return;
|
||||
|
||||
if (si_cs_send(cs))
|
||||
si_rx_room_rdy(si_opposite(si));
|
||||
si_cs_send(cs);
|
||||
}
|
||||
|
||||
/* Updates at once the channel flags, and timers of both stream interfaces of a
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user