diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c index 5f84b1183..45adb9fbb 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -2724,13 +2724,42 @@ static void fcgi_process_demux(struct fcgi_conn *fconn) fcgi_conn_restart_reading(fconn, 0); } +/* resume each fstrm eligible for sending in list head */ +static void fcgi_resume_each_sending_fstrm(struct fcgi_conn *fconn, struct list *head) +{ + struct fcgi_strm *fstrm, *fstrm_back; + + TRACE_ENTER(FCGI_EV_FCONN_SEND|FCGI_EV_FCONN_WAKE, fconn->conn); + + list_for_each_entry_safe(fstrm, fstrm_back, &fconn->send_list, send_list) { + if (fconn->state == FCGI_CS_CLOSED || fconn->flags & FCGI_CF_MUX_BLOCK_ANY) + break; + + fstrm->flags &= ~FCGI_SF_BLK_ANY; + + if (fstrm->flags & FCGI_SF_NOTIFIED) + continue; + + /* If the sender changed his mind and unsubscribed, let's just + * remove the stream from the send_list. + */ + if (!(fstrm->flags & (FCGI_SF_WANT_SHUTR|FCGI_SF_WANT_SHUTW)) && + (!fstrm->subs || !(fstrm->subs->events & SUB_RETRY_SEND))) { + LIST_DEL_INIT(&fstrm->send_list); + continue; + } + + fcgi_strm_notify_send(fstrm); + } + + TRACE_LEAVE(FCGI_EV_FCONN_SEND|FCGI_EV_FCONN_WAKE, fconn->conn); +} + /* process Tx records from streams to be multiplexed. Returns > 0 if it reached * the end. */ static int fcgi_process_mux(struct fcgi_conn *fconn) { - struct fcgi_strm *fstrm, *fstrm_back; - TRACE_ENTER(FCGI_EV_FCONN_WAKE, fconn->conn); if (unlikely(fconn->state < FCGI_CS_RECORD_H)) { @@ -2753,36 +2782,7 @@ static int fcgi_process_mux(struct fcgi_conn *fconn) } mux: - list_for_each_entry_safe(fstrm, fstrm_back, &fconn->send_list, send_list) { - if (fconn->state == FCGI_CS_CLOSED || fconn->flags & FCGI_CF_MUX_BLOCK_ANY) - break; - - if (fstrm->flags & FCGI_SF_NOTIFIED) - continue; - - /* If the sender changed his mind and unsubscribed, let's just - * remove the stream from the send_list. - */ - if (!(fstrm->flags & (FCGI_SF_WANT_SHUTR|FCGI_SF_WANT_SHUTW)) && - (!fstrm->subs || !(fstrm->subs->events & SUB_RETRY_SEND))) { - LIST_DEL_INIT(&fstrm->send_list); - continue; - } - - if (fstrm->subs && fstrm->subs->events & SUB_RETRY_SEND) { - TRACE_POINT(FCGI_EV_STRM_WAKE, fconn->conn, fstrm); - fstrm->flags &= ~FCGI_SF_BLK_ANY; - fstrm->flags |= FCGI_SF_NOTIFIED; - tasklet_wakeup(fstrm->subs->tasklet); - fstrm->subs->events &= ~SUB_RETRY_SEND; - if (!fstrm->subs->events) - fstrm->subs = NULL; - } else { - /* it's the shut request that was queued */ - TRACE_POINT(FCGI_EV_STRM_WAKE, fconn->conn, fstrm); - tasklet_wakeup(fstrm->shut_tl); - } - } + fcgi_resume_each_sending_fstrm(fconn, &fconn->send_list); fail: if (fconn->state == FCGI_CS_CLOSED) { @@ -2986,40 +2986,9 @@ static int fcgi_send(struct fcgi_conn *fconn) /* We're not full anymore, so we can wake any task that are waiting * for us. */ - if (!(fconn->flags & (FCGI_CF_MUX_MFULL | FCGI_CF_DEM_MROOM)) && fconn->state >= FCGI_CS_RECORD_H) { - struct fcgi_strm *fstrm, *fstrm_back; + if (!(fconn->flags & (FCGI_CF_MUX_MFULL | FCGI_CF_DEM_MROOM)) && fconn->state >= FCGI_CS_RECORD_H) + fcgi_resume_each_sending_fstrm(fconn, &fconn->send_list); - list_for_each_entry_safe(fstrm, fstrm_back, &fconn->send_list, send_list) { - if (fconn->state == FCGI_CS_CLOSED || fconn->flags & FCGI_CF_MUX_BLOCK_ANY) - break; - - if (fstrm->flags & FCGI_SF_NOTIFIED) - continue; - - /* If the sender changed his mind and unsubscribed, let's just - * remove the stream from the send_list. - */ - if (!(fstrm->flags & (FCGI_SF_WANT_SHUTR|FCGI_SF_WANT_SHUTW)) && - (!fstrm->subs || !(fstrm->subs->events & SUB_RETRY_SEND))) { - LIST_DEL_INIT(&fstrm->send_list); - continue; - } - - if (fstrm->subs && fstrm->subs->events & SUB_RETRY_SEND) { - TRACE_DEVEL("waking up pending stream", FCGI_EV_FCONN_SEND|FCGI_EV_STRM_WAKE, conn, fstrm); - fstrm->flags &= ~FCGI_SF_BLK_ANY; - fstrm->flags |= FCGI_SF_NOTIFIED; - tasklet_wakeup(fstrm->subs->tasklet); - fstrm->subs->events &= ~SUB_RETRY_SEND; - if (!fstrm->subs->events) - fstrm->subs = NULL; - } else { - /* it's the shut request that was queued */ - TRACE_POINT(FCGI_EV_STRM_WAKE, fconn->conn, fstrm); - tasklet_wakeup(fstrm->shut_tl); - } - } - } /* We're done, no more to send */ if (!br_data(fconn->mbuf)) { TRACE_DEVEL("leaving with everything sent", FCGI_EV_FCONN_SEND, conn);