{
struct wait_event *sw;
- if (h2s->send_wait && !(h2s->send_wait->events & SUB_CALL_UNSUBSCRIBE)) {
+ if (h2s->send_wait && LIST_ISEMPTY(&h2s->sending_list)) {
sw = h2s->send_wait;
sw->events &= ~SUB_RETRY_SEND;
- sw->events |= SUB_CALL_UNSUBSCRIBE;
LIST_ADDQ(&h2s->h2c->sending_list, &h2s->sending_list);
tasklet_wakeup(sw->task);
}
* we're in it, we're getting out anyway
*/
LIST_DEL_INIT(&h2s->list);
- LIST_DEL_INIT(&h2s->sending_list);
+ if (!LIST_ISEMPTY(&h2s->sending_list)) {
+ task_remove_from_tasklet_list((struct task *)h2s->send_wait->task);
+ LIST_DEL_INIT(&h2s->sending_list);
+ }
tasklet_free(h2s->wait_event.task);
pool_free(pool_head_h2s, h2s);
}
*/
static int h2_process_mux(struct h2c *h2c)
{
- struct h2s *h2s;
+ struct h2s *h2s, *h2s_back;
if (unlikely(h2c->st0 < H2_CS_FRAME_H)) {
if (unlikely(h2c->st0 == H2_CS_PREFACE && (h2c->flags & H2_CF_IS_BACK))) {
* blocked just on this.
*/
- list_for_each_entry(h2s, &h2c->fctl_list, list) {
+ list_for_each_entry_safe(h2s, h2s_back, &h2c->fctl_list, list) {
if (h2c->mws <= 0 || h2c->flags & H2_CF_MUX_BLOCK_ANY ||
h2c->st0 >= H2_CS_ERROR)
break;
- if (h2s->send_wait->events & SUB_CALL_UNSUBSCRIBE)
+
+ if (!LIST_ISEMPTY(&h2s->sending_list))
continue;
h2s->flags &= ~H2_SF_BLK_ANY;
+ /* For some reason, the upper layer failed to subsribe again,
+ * so remove it from the send_list
+ */
+ if (!h2s->send_wait) {
+ LIST_DEL_INIT(&h2s->list);
+ continue;
+ }
h2s->send_wait->events &= ~SUB_RETRY_SEND;
- h2s->send_wait->events |= SUB_CALL_UNSUBSCRIBE;
LIST_ADDQ(&h2c->sending_list, &h2s->sending_list);
tasklet_wakeup(h2s->send_wait->task);
}
- list_for_each_entry(h2s, &h2c->send_list, list) {
+ list_for_each_entry_safe(h2s, h2s_back, &h2c->send_list, list) {
if (h2c->st0 >= H2_CS_ERROR || h2c->flags & H2_CF_MUX_BLOCK_ANY)
break;
- if (h2s->send_wait->events & SUB_CALL_UNSUBSCRIBE)
+
+ if (!LIST_ISEMPTY(&h2s->sending_list))
continue;
+ /* For some reason, the upper layer failed to subsribe again,
+ * so remove it from the send_list
+ */
+ if (!h2s->send_wait) {
+ LIST_DEL_INIT(&h2s->list);
+ continue;
+ }
h2s->flags &= ~H2_SF_BLK_ANY;
h2s->send_wait->events &= ~SUB_RETRY_SEND;
- h2s->send_wait->events |= SUB_CALL_UNSUBSCRIBE;
LIST_ADDQ(&h2c->sending_list, &h2s->sending_list);
tasklet_wakeup(h2s->send_wait->task);
}
list_for_each_entry(h2s, &h2c->send_list, list) {
if (h2c->st0 >= H2_CS_ERROR || h2c->flags & H2_CF_MUX_BLOCK_ANY)
break;
- if (h2s->send_wait->events & SUB_CALL_UNSUBSCRIBE)
+
+ if (!LIST_ISEMPTY(&h2s->sending_list))
continue;
+ /* For some reason, the upper layer failed to subsribe again,
+ * so remove it from the send_list
+ */
+ if (!h2s->send_wait) {
+ LIST_DEL_INIT(&h2s->list);
+ continue;
+ }
h2s->flags &= ~H2_SF_BLK_ANY;
h2s->send_wait->events &= ~SUB_RETRY_SEND;
- h2s->send_wait->events |= SUB_CALL_UNSUBSCRIBE;
tasklet_wakeup(h2s->send_wait->task);
LIST_ADDQ(&h2c->sending_list, &h2s->sending_list);
}
if (!h2s)
return;
+ /* The stream is about to die, so no need to attempt to run its task */
+ if (!LIST_ISEMPTY(&h2s->sending_list) &&
+ h2s->send_wait != &h2s->wait_event) {
+ task_remove_from_tasklet_list((struct task *)h2s->send_wait->task);
+ LIST_DEL_INIT(&h2s->sending_list);
+ }
+
sess = h2s->sess;
h2c = h2s->h2c;
h2s->cs = NULL;
int ret = 0;
LIST_DEL_INIT(&h2s->sending_list);
- if (h2s->send_wait) {
- h2s->send_wait->events &= ~SUB_CALL_UNSUBSCRIBE;
- h2s->send_wait->events |= SUB_RETRY_SEND;
- }
if (reason & 2)
ret |= h2_do_shutw(h2s);
if (reason & 1)
if (!ret) {
/* We're done trying to send, remove ourself from the send_list */
- h2s->send_wait->events &= ~SUB_RETRY_SEND;
- h2s->send_wait = NULL;
LIST_DEL_INIT(&h2s->list);
}
/* We're no longer trying to send anything, let's destroy the h2s */
LIST_DEL(&h2s->list);
LIST_INIT(&h2s->list);
sw->events &= ~SUB_RETRY_SEND;
+ /* We were about to send, make sure it does not happen */
+ if (!LIST_ISEMPTY(&h2s->sending_list) &&
+ h2s->send_wait != &h2s->wait_event) {
+ task_remove_from_tasklet_list((struct task *)h2s->send_wait->task);
+ LIST_DEL_INIT(&h2s->sending_list);
+ }
h2s->send_wait = NULL;
- }
- }
- if (event_type & SUB_CALL_UNSUBSCRIBE) {
- sw = param;
- if (h2s->send_wait == sw) {
- sw->events &= ~SUB_CALL_UNSUBSCRIBE;
- task_remove_from_tasklet_list((struct task *)h2s->send_wait->task);
- h2s->send_wait = NULL;
- LIST_DEL(&h2s->list);
- LIST_INIT(&h2s->list);
- LIST_DEL_INIT(&h2s->sending_list);
+
}
}
return 0;
LIST_DEL_INIT(&h2s->sending_list);
task_remove_from_tasklet_list((struct task *)h2s->send_wait->task);
h2s->send_wait->events |= SUB_RETRY_SEND;
- h2s->send_wait->events &= ~SUB_CALL_UNSUBSCRIBE;
}
}
* and there's somebody else that is waiting to send, do nothing,
* we will subscribe later and be put at the end of the list
*/
- LIST_DEL_INIT(&h2s->sending_list);
- if ((!(h2s->send_wait) || !(h2s->send_wait->events & SUB_CALL_UNSUBSCRIBE)) &&
+ if (LIST_ISEMPTY(&h2s->sending_list) &&
(!LIST_ISEMPTY(&h2s->h2c->send_list) || !LIST_ISEMPTY(&h2s->h2c->fctl_list)))
return 0;
+ LIST_DEL_INIT(&h2s->sending_list);
+
+ /* We couldn't set it to NULL before, because we needed it in case
+ * we had to cancel the tasklet
+ */
+ h2s->send_wait = NULL;
- if (h2s->send_wait) {
- /* We want to stay in the send_list, so prepare ourself to be
- * eventually recalled if needed, and only remove ourself from
- * the list if we managed to send anything.
- */
- h2s->send_wait->events &= ~SUB_CALL_UNSUBSCRIBE;
- h2s->send_wait->events |= SUB_RETRY_SEND;
- }
if (h2s->h2c->st0 < H2_CS_FRAME_H)
return 0;
else
cs->flags |= CS_FL_ERR_PENDING;
}
- if (total > 0 && h2s->send_wait) {
+ if (total > 0) {
/* Ok we managed to send something, leave the send_list */
- h2s->send_wait->events &= ~SUB_RETRY_SEND;
- h2s->send_wait = NULL;
LIST_DEL_INIT(&h2s->list);
}
return total;