[SERVER-59509] Scheduling on ScopedTaskExecutor after underlying executor is shutdown invariants Created: 23/Aug/21  Updated: 06/Dec/22

Status: Backlog
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: George Wangensteen Assignee: Backlog - Service Architecture
Resolution: Unresolved Votes: 0
Labels: sa-remove-fv-backlog-22
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Service Arch
Operating System: ALL
Steps To Reproduce:

Minimal repro, add this to scoped_task_executor_test.cpp:

TEST_F(ScopedTaskExecutorTest, ShutdownUnderlyingThenSchedule) {
    ScopedTaskExecutor exec(getUnderlying());
    getUnderlying()->shutdown();
    int x = 2;
    exec->schedule([&](Status) { x += 2; });
}

Participants:

 Description   

The ScopedTaskExecutor wraps another "underlying" TaskExecutor that it forwards work to actually be executed on. When work is scheduled on the ScopedTaskExecutor after the underlying executor is shutdown, this invariant in TaskExecutor::schedule is triggered.

 

Here's a brief explanation as to why: say exec is a ScopedTaskExecutor. When exec->schedule(...) is called:

1) The member-of-pointer operator on ScopedTaskExecutor returns a TaskExecutor*, which actually points to a ScopedTaskExecutor::Impl, which inherits from TaskExecutor. 

2) TaskExecutor::schedule is called, and then calls the member scheduleWork; because the actual type here is ScopedTaskExecutor::Impl, we use its definition of scheduleWork here

3) The ScopedTaskExecutor attempts to wrap the provided Task in a lambda here, where it captures the provided Task by forwarding it into the lambda. This will invoke the move assignment operator and invalidate the provided Task 

4) The ScopedTaskExecutor attempts to schedule the wrapped Task on the underlying executor, which refuses because it is shutdown, and returns a bad status.

5) The ScopedTaskExecutor propagates the bad status up to TaskExecutor::schedule. However, it has broken the contract of scheduleWork, by returning a bad status (failing to schedule) and invalidating the provided Task. Therefore, the invariant is hit. 


Generated at Thu Feb 08 05:47:25 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.