Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Ethereum capability work loop can be cancelled prematurely #5508

@halfalicious

Description

@halfalicious

Ethereum capabilities make use of boost deadline timers to schedule their work loop via Host::scheduleExecution - for example:

void EthereumCapability::onStarting()
{
m_backgroundWorkEnabled = true;
m_host->scheduleExecution(c_backroundWorkPeriodMs, [this]() { doBackgroundWork(); });
}

...and in EthereumCapability::doBackgroundWork:

if (m_backgroundWorkEnabled)
m_host->scheduleExecution(c_backroundWorkPeriodMs, [this]() { doBackgroundWork(); });
}

Note that Host's usage of deadline timers is susceptible to a race condition - Host::scheduleExecution creates a new timer, adds it to a list, and performs an async_wait on it. The host then "garbage collects" expired timers in Host::run, and it determines if a timer is expired by checking its expiration time:

aleth/libp2p/Host.cpp

Lines 687 to 692 in 9e5a853

DEV_GUARDED(x_networkTimers)
{
m_networkTimers.remove_if([](unique_ptr<io::deadline_timer> const& t) {
return t->expires_from_now().total_milliseconds() < 0;
});
}

However, note that when a timer expires, its handler is put into a queue rather than being executed immediately - this means that there's a race condition where a handler can be executed after the timer has been deleted, resulting in the handler being executed with boost error code operation_aborted, which will result in the handler immediately exiting without executing any of its core logic.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions