Description
The related code here:
void UnixNetVConnection::reenable(VIO *vio) { if (STATE_FROM_VIO(vio)->enabled) return; set_enabled(vio); if (!thread) return; EThread *t = vio->mutex->thread_holding; ink_assert(t == this_ethread()); ink_release_assert(!closed); if (nh->mutex->thread_holding == t) { ... MUTEX_TRY_LOCK(lock, nh->mutex, t); if (!lock.is_locked()) { if (vio == &read.vio) { if (!read.in_enabled_list) { // -----------> the condition check is not atomic read.in_enabled_list = 1; // -----------> the variable set is not atomic nh->read_enable_list.push(this); } } else { if (!write.in_enabled_list) { // -----------> the write side write.in_enabled_list = 1; // -----------> the write side nh->write_enable_list.push(this); } } if (nh->trigger_event && nh->trigger_event->ethread->signal_hook) nh->trigger_event->ethread->signal_hook(nh->trigger_event->ethread); } else { ... } } }
Due to the unstable condition check code, the nh->read_enable_list.push(this) would push a netvc into atomic queue that is already inside a queue.
It leads the elements in atomic queue after the netvc will be lost.