mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 13:51:26 +02:00
[MEDIUM] stream_sock_read: call ->chk_snd whenever there are data pending
The condition to cakk ->chk_snd() in stream_sock_read() was suboptimal because we did not call it when the socket was shut down nor when there was an error after data were added. Now we ensure to call is whenever there are data pending. Also, the "full" condition was handled before calling chk_snd(), which could cause deadlock issues if chk_snd() did consume some data.
This commit is contained in:
parent
0c2fc1f39d
commit
9c0fe59612
@ -40,7 +40,6 @@
|
|||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
int stream_sock_read(int fd) {
|
int stream_sock_read(int fd) {
|
||||||
__label__ out_wakeup, out_shutdown_r, out_error;
|
|
||||||
struct stream_interface *si = fdtab[fd].owner;
|
struct stream_interface *si = fdtab[fd].owner;
|
||||||
struct buffer *b = si->ib;
|
struct buffer *b = si->ib;
|
||||||
int ret, max, retval, cur_read;
|
int ret, max, retval, cur_read;
|
||||||
@ -79,8 +78,10 @@ int stream_sock_read(int fd) {
|
|||||||
max = b->max_len;
|
max = b->max_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max == 0)
|
if (max == 0) {
|
||||||
goto out_full;
|
b->flags |= BF_FULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2. read the largest possible block
|
* 2. read the largest possible block
|
||||||
@ -155,7 +156,9 @@ int stream_sock_read(int fd) {
|
|||||||
b->xfer_small = 0;
|
b->xfer_small = 0;
|
||||||
b->xfer_large = 0;
|
b->xfer_large = 0;
|
||||||
}
|
}
|
||||||
goto out_full;
|
|
||||||
|
b->flags |= BF_FULL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if too many bytes were missing from last read, it means that
|
/* if too many bytes were missing from last read, it means that
|
||||||
@ -227,44 +230,34 @@ int stream_sock_read(int fd) {
|
|||||||
}
|
}
|
||||||
} /* while (1) */
|
} /* while (1) */
|
||||||
|
|
||||||
/*
|
|
||||||
* The only way to get out of this loop is to have stopped reading
|
|
||||||
* without any error nor close, either by limiting the number of
|
|
||||||
* loops, or because of an EAGAIN. We only rearm the timer if we
|
|
||||||
* have at least read something.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((b->flags & (BF_READ_PARTIAL|BF_FULL|BF_READ_NOEXP)) == BF_READ_PARTIAL)
|
|
||||||
b->rex = tick_add_ifset(now_ms, b->rto);
|
|
||||||
|
|
||||||
if (!(b->flags & BF_READ_ACTIVITY))
|
|
||||||
goto out_skip_wakeup;
|
|
||||||
out_wakeup:
|
out_wakeup:
|
||||||
/* the consumer might be waiting for data */
|
/* We might have some data the consumer is waiting for */
|
||||||
if (likely((b->flags & (BF_READ_PARTIAL|BF_EMPTY)) == BF_READ_PARTIAL &&
|
if (likely((b->send_max || b->splice_len) &&
|
||||||
(b->cons->flags & SI_FL_WAIT_DATA)))
|
(b->cons->flags & SI_FL_WAIT_DATA)))
|
||||||
b->cons->chk_snd(b->cons);
|
b->cons->chk_snd(b->cons);
|
||||||
|
|
||||||
|
/* note that the consumer might have cleared BF_FULL */
|
||||||
|
if ((b->flags & (BF_READ_PARTIAL|BF_FULL|BF_READ_NOEXP)) == BF_READ_PARTIAL)
|
||||||
|
b->rex = tick_add_ifset(now_ms, b->rto);
|
||||||
|
else if (b->flags & BF_FULL) {
|
||||||
|
si->flags |= SI_FL_WAIT_ROOM;
|
||||||
|
EV_FD_CLR(fd, DIR_RD);
|
||||||
|
b->rex = TICK_ETERNITY;
|
||||||
|
}
|
||||||
|
|
||||||
/* we have to wake up if there is a special event or if we don't have
|
/* we have to wake up if there is a special event or if we don't have
|
||||||
* any more data to forward.
|
* any more data to forward.
|
||||||
*/
|
*/
|
||||||
if (likely((b->flags & (BF_READ_NULL|BF_READ_ERROR|BF_SHUTR)) ||
|
if (likely((b->flags & (BF_READ_NULL|BF_READ_ERROR|BF_SHUTR)) ||
|
||||||
!b->to_forward ||
|
!b->to_forward ||
|
||||||
si->state != SI_ST_EST ||
|
si->state != SI_ST_EST ||
|
||||||
b->cons->state != SI_ST_EST))
|
b->cons->state != SI_ST_EST ||
|
||||||
|
(si->flags & SI_FL_ERR)))
|
||||||
task_wakeup(si->owner, TASK_WOKEN_IO);
|
task_wakeup(si->owner, TASK_WOKEN_IO);
|
||||||
|
|
||||||
out_skip_wakeup:
|
|
||||||
fdtab[fd].ev &= ~FD_POLL_IN;
|
fdtab[fd].ev &= ~FD_POLL_IN;
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
out_full:
|
|
||||||
si->flags |= SI_FL_WAIT_ROOM;
|
|
||||||
b->flags |= BF_FULL;
|
|
||||||
EV_FD_CLR(fd, DIR_RD);
|
|
||||||
b->rex = TICK_ETERNITY;
|
|
||||||
goto out_wakeup;
|
|
||||||
|
|
||||||
out_shutdown_r:
|
out_shutdown_r:
|
||||||
/* we received a shutdown */
|
/* we received a shutdown */
|
||||||
fdtab[fd].ev &= ~FD_POLL_HUP;
|
fdtab[fd].ev &= ~FD_POLL_HUP;
|
||||||
@ -283,8 +276,8 @@ int stream_sock_read(int fd) {
|
|||||||
fdtab[fd].state = FD_STERROR;
|
fdtab[fd].state = FD_STERROR;
|
||||||
fdtab[fd].ev &= ~FD_POLL_STICKY;
|
fdtab[fd].ev &= ~FD_POLL_STICKY;
|
||||||
si->flags |= SI_FL_ERR;
|
si->flags |= SI_FL_ERR;
|
||||||
task_wakeup(si->owner, TASK_WOKEN_IO);
|
retval = 1;
|
||||||
return 1;
|
goto out_wakeup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user