Merge branch 'maint-0.3.2' into release-0.3.2

This commit is contained in:
Nick Mathewson 2018-02-02 12:03:54 -05:00
commit f5e37b2eb6
2 changed files with 27 additions and 11 deletions

View File

@ -628,17 +628,21 @@ scheduler_release_channel,(channel_t *chan))
return; return;
} }
if (chan->scheduler_state == SCHED_CHAN_PENDING) { /* Try to remove the channel from the pending list regardless of its
if (SCHED_BUG(smartlist_pos(channels_pending, chan) == -1, chan)) { * scheduler state. We can release a channel in many places in the tor code
log_warn(LD_SCHED, "Scheduler asked to release channel %" PRIu64 " " * so we can't rely on the channel state (PENDING) to remove it from the
"but it wasn't in channels_pending", * list.
chan->global_identifier); *
} else { * For instance, the channel can change state from OPEN to CLOSING while
smartlist_pqueue_remove(channels_pending, * being handled in the scheduler loop leading to the channel being in
scheduler_compare_channels, * PENDING state but not in the pending list. Furthermore, we release the
offsetof(channel_t, sched_heap_idx), * channel when it changes state to close and a second time when we free it.
chan); * Not ideal at all but for now that is the way it is. */
} if (chan->sched_heap_idx != -1) {
smartlist_pqueue_remove(channels_pending,
scheduler_compare_channels,
offsetof(channel_t, sched_heap_idx),
chan);
} }
if (the_scheduler->on_channel_free) { if (the_scheduler->on_channel_free) {

View File

@ -502,6 +502,18 @@ perform_channel_state_tests(int KISTSchedRunInterval, int sched_type)
scheduler_touch_channel(ch1); scheduler_touch_channel(ch1);
tt_assert(scheduler_compare_channels_mock_ctr > old_count); tt_assert(scheduler_compare_channels_mock_ctr > old_count);
/* Release the ch2 and then do it another time to make sure it doesn't blow
* up and we are still in a quiescent state. */
scheduler_release_channel(ch2);
tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
/* Cheat a bit so make the release more confused but also will tells us if
* the release did put the channel in the right state. */
ch2->scheduler_state = SCHED_CHAN_PENDING;
scheduler_release_channel(ch2);
tt_int_op(ch2->scheduler_state, OP_EQ, SCHED_CHAN_IDLE);
tt_int_op(smartlist_len(channels_pending), OP_EQ, 1);
/* Close */ /* Close */
channel_mark_for_close(ch1); channel_mark_for_close(ch1);
tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING); tt_int_op(ch1->state, OP_EQ, CHANNEL_STATE_CLOSING);