Python engineer reviewing cancelled pending futures and tasks still running after ThreadPoolExecutor shutdown.

Executor Shutdown Returned. Which Python Futures Were Still Running?

Thu, Nov 12, 2026

ThreadPoolExecutor.shutdown(cancel_futures=True, wait=False) can return while submitted work is still executing. That is not an implementation accident: Python documents wait=False as allowing shutdown() to return without waiting for outstanding work to finish, while cancel_futures=True applies only to futures that have not started running. Futures that are already running are not cancelled.

That creates a dangerous false-positive success signal in operational code. A caller sees shutdown() return normally and may record “executor stopped,” “jobs cancelled,” or even “cleanup complete.” None of those conclusions follows from the API return alone. The actual state can contain both successfully cancelled pending futures and still-running futures whose callables remain active. Python's Future API makes those states separately observable: cancelled() reports successful cancellation, running() reports current execution that can no longer be cancelled, and done() includes both finished and cancelled futures.

The acceptance problem is therefore narrow: prove which futures had crossed the pending-to-running boundary when shutdown was requested, prove which queued futures were cancelled, and do not infer either fact from the successful return of shutdown().

This playbook defines a disposable standard-library-only fixture pinned to CPython 3.14.10, synthetic task identities, deterministic execution barriers, an independent expected-case manifest, a per-case evidence ledger, explicit negative and comparison controls, and a final ACCEPT / REPAIR / RERUN / HOLD decision. No execution is claimed here. Every behavioral result below is EXPECTED / NOT EXECUTED until a commissioning run produces the corresponding evidence.

Define the acceptance contract

Start with the public contract, not the CPython implementation.

For Python 3.14.10, Executor.shutdown(wait=False) is documented to return without waiting until outstanding futures finish; resources are released when the outstanding work is done. cancel_futures=True cancels pending futures that have not started. Running and already-completed futures are not cancelled. Python also states that the interpreter itself will not exit while executor work remains pending.

That yields an acceptance contract with three separate propositions:

Proposition

Required proof

Invalid substitute

Shutdown request was accepted

shutdown(cancel_futures=True, wait=False) returned without exception

“all work stopped”

A future was pending and cancelled

future.cancelled() is True and future.done() is True

shutdown returned

A future was executing

controlled worker-start evidence plus future.running() is True at the post-shutdown observation

future was merely submitted

The key phrase is post-shutdown observation. The fixture should not ask only whether a task ran eventually. It should record whether a task had definitely begun before shutdown and whether the corresponding future remained running immediately after shutdown() returned.

This differs materially from Refonte Learning's Machine learning evaluation. That article evaluates predictive performance using data splits, baselines, error metrics, thresholds and generalization evidence; its audience is engineers and practitioners deciding whether a model's performance claim is defensible. Here the test oracle is not statistical and no learned model exists. The reusable principle is only “define acceptance before observing results”.

For this article, approve only if the evidence establishes all of the following:

  1. exactly the intended worker futures crossed into execution before shutdown;

  2. known queued futures were cancelled rather than executed;

  3. shutdown returned before blocked running work completed;

  4. the same fixture without cancel_futures=True produces a distinguishable queued-work outcome;

  5. identities in the manifest, worker ledger and Future snapshots reconcile one-for-one.

All five are EXPECTED / NOT EXECUTED until evidence exists.

Capture a pinned baseline

A versioned-behavior investigation is weak if “Python 3” is the only runtime description. Pin both the public documentation and the implementation inspected during review.

This playbook targets CPython 3.14.10, released October 25, 2026. Python.org currently lists 3.14.10 as a Python 3.14 maintenance release, alongside Python 3.15 as the newer feature series. The relevant Python 3.14 documentation currently identifies itself as 3.14.10 documentation.

The baseline capture should contain the interpreter version, implementation, executable path, platform string and hash of the fixture:

python3 - <<'PY'
import hashlib
import pathlib
import platform
import sys

expected = (3, 14, 10)
assert sys.implementation.name == "cpython", sys.implementation.name
assert sys.version_info[:3] == expected, sys.version

fixture = pathlib.Path("executor_shutdown_fixture.py")
print("implementation=", sys.implementation.name)
print("version=", sys.version)
print("executable=", sys.executable)
print("platform=", platform.platform())
print("fixture_sha256=", hashlib.sha256(fixture.read_bytes()).hexdigest())
PY

Save this as evidence/baseline.txt rather than relying on terminal history.

The implementation tag matters because CPython's ThreadPoolExecutor.shutdown() currently acquires its shutdown lock, marks the executor shut down, drains queued work when cancel_futures=True, calls cancel() on each drained work item's future, adds a sentinel to wake workers, and joins worker threads only when wait is true. That implementation is supporting evidence, not the primary API guarantee: applications should derive their portable contract from documented Executor and Future semantics.

Pin fixture versions

Pass condition: sys.implementation.name == "cpython" and sys.version_info[:3] == (3, 14, 10) before any behavioral case runs.

Fail condition: any other interpreter or patch release.

A version mismatch does not prove the behavior is wrong; it proves this evidence packet does not belong to the declared baseline. Record RERUN after intentionally repinning and reviewing the matching documentation and source. Do not silently relabel output from 3.14.9, 3.15.2 or another implementation as 3.14.10 evidence.

Status for this article: EXPECTED / NOT EXECUTED.

Create an isolated fixture

Use standard-library synchronization rather than sleeps to establish the critical ordering. threading.Event.wait() blocks until another thread sets the event, making it suitable for holding already-started worker functions at a known barrier. A thread-safe queue.Queue is suitable for transferring structured worker events to the main thread; Python documents queue as a synchronized multi-producer, multi-consumer mechanism.

Create a disposable directory:

tmpdir="$(mktemp -d)"
cd "$tmpdir"

python3.14 -m venv .venv
. .venv/bin/activate
python -VV
mkdir -p evidence

Do not use a ThreadPoolExecutor context manager around the critical test. Python documents context-manager exit as shutting down while waiting as though shutdown(wait=True) had been used; that would obscure the exact wait=False return boundary this fixture is designed to inspect.

The core worker records identity before it blocks:

from queue import Queue
from threading import Event, current_thread

events = Queue()
release = Event()

def blocked_worker(case_id: str, task_id: str):
    events.put({
        "kind": "worker_started",
        "case": case_id,
        "task": task_id,
        "thread": current_thread().name,
    })
    release.wait()
    events.put({
        "kind": "worker_released",
        "case": case_id,
        "task": task_id,
        "thread": current_thread().name,
    })
    return task_id

The task's first ledger write occurs inside the callable, so receipt of worker_started independently proves that user work began. Do not use thread-name existence, executor private members or Queue.qsize() as the oracle. Python explicitly warns that queue size methods are approximate and do not guarantee what a subsequent queue operation will do.

The Asyncio context capture article is adjacent but distinct. It investigates when asyncio.to_thread() captures contextvars.Context, including the difference between coroutine construction and later execution. This fixture has no asyncio, no ContextVar, and no capture-timing requirement. Its boundary is a concurrent.futures.Future moving from pending to running.

Write the expected-case manifest

An independent test oracle should exist before the executor is created. Do not generate “expected” states by inspecting the same Future objects whose behavior you are validating.

Store expected.json:

{
  "runtime": {
    "implementation": "cpython",
    "version": "3.14.10"
  },
  "cases": {
    "cancel_pending": {
      "shutdown": {"cancel_futures": true, "wait": false},
      "workers": 2,
      "tasks": {
        "run-A": "running_after_shutdown_return",
        "run-B": "running_after_shutdown_return",
        "queue-C": "cancelled",
        "queue-D": "cancelled",
        "queue-E": "cancelled"
      }
    },
    "keep_pending": {
      "shutdown": {"cancel_futures": false, "wait": false},
      "workers": 2,
      "tasks": {
        "run-A": "running_after_shutdown_return",
        "run-B": "running_after_shutdown_return",
        "queue-C": "not_cancelled",
        "queue-D": "not_cancelled",
        "queue-E": "not_cancelled"
      }
    }
  }
}

The manifest deliberately avoids promising that a non-cancelled queued future will remain pending at every arbitrary later instant. Once the two blocker tasks are released, workers may execute queued work. The comparison invariant is simply that the queued futures are not cancelled by shutdown when cancel_futures=False, whereas they are expected to be cancelled when cancel_futures=True. That distinction tracks the documented API without imposing unsupported scheduling guarantees.

The manifest should also declare evidence requirements:

{
  "required_evidence": [
    "runtime_pin",
    "worker_started_for_run_A",
    "worker_started_for_run_B",
    "shutdown_return",
    "future_snapshot_after_return",
    "worker_release",
    "terminal_reconciliation"
  ]
}

A test that produces the desired final counts but loses task identity is not equivalent evidence.

Establish a negative control

Before calling shutdown, attempt to cancel one task known to be running:

assert futures["run-A"].running()
negative_cancel = futures["run-A"].cancel()

Python documents that Future.cancel() returns False when the call is already executing or has finished and therefore cannot be cancelled. It also defines running() as true when the call is currently executing and cannot be cancelled.

Pass condition: the worker-start event for run-A was received, run-A.running() is true, and run-A.cancel() returns false.

Fail condition: the ordering evidence is missing or cancellation succeeds.

Status: EXPECTED / NOT EXECUTED.

Reproduce the misleading success

The primary case deliberately fills both worker slots before submitting more work.

The complete sequencing logic is:

from concurrent.futures import ThreadPoolExecutor
from queue import Empty
import time
executor = ThreadPoolExecutor(
    max_workers=2,
    thread_name_prefix="shutdown-proof",
)
futures = {}
futures["run-A"] = executor.submit(
    blocked_worker, "cancel_pending", "run-A"
)
futures["run-B"] = executor.submit(
    blocked_worker, "cancel_pending", "run-B"
)
started = set()
deadline = time.monotonic() + 5.0
while started != {"run-A", "run-B"}:
    remaining = deadline - time.monotonic()
    if remaining <= 0:
        raise RuntimeError("HOLD: running barrier not established")
    event = events.get(timeout=remaining)
    if event["kind"] == "worker_started":
        started.add(event["task"])
for task_id in ("queue-C", "queue-D", "queue-E"):
    futures[task_id] = executor.submit(
        blocked_worker, "cancel_pending", task_id
    )
assert futures["run-A"].running()
assert futures["run-B"].running()
t0 = time.monotonic_ns()
executor.shutdown(cancel_futures=True, wait=False)
t1 = time.monotonic_ns()

At that moment, the strongest legitimate conclusion is: shutdown returned. The documentation explicitly allows that return while unfinished futures remain.

Now snapshot all five futures before releasing the blocker:

snapshot = {
    task_id: {
        "cancelled": f.cancelled(),
        "running": f.running(),
        "done": f.done(),
    }
    for task_id, f in futures.items()
}

Expected state:

Task

Expected immediately after return

Status

run-A

running=true, cancelled=false, done=false

EXPECTED / NOT EXECUTED

run-B

running=true, cancelled=false, done=false

EXPECTED / NOT EXECUTED

queue-C

running=false, cancelled=true, done=true

EXPECTED / NOT EXECUTED

queue-D

running=false, cancelled=true, done=true

EXPECTED / NOT EXECUTED

queue-E

running=false, cancelled=true, done=true

EXPECTED / NOT EXECUTED

done=True on cancelled work is not a contradiction. Python defines done() as true when a call either completed or was successfully cancelled.

The false positive would be reporting the first row of evidence (“shutdown returned”) as equivalent to all five tasks having stopped.

Run the comparison case

A comparison case needs one controlled change. Keep task identities, worker count, synchronization and submission order the same, but call:

executor.shutdown(cancel_futures=False, wait=False)

The two blocked futures should still be running because wait=False does not wait for them. The three queued futures, however, should not be cancelled by shutdown. Python's documentation assigns automatic pending cancellation specifically to cancel_futures=True.

Do not release the gate until the post-return snapshot is written. Then:

release.set()

The queued calls may subsequently start and complete because they were retained rather than cancelled. This is exactly why terminal state alone is insufficient: after enough time, both the cancel_futures=True and False cases could contain only done() futures, but for different reasons. One set was cancelled before execution; the other may have run.

The Kubernetes preStop article provides a useful adjacent contrast. Its acceptance question is whether preStop consumed part of a Pod's shared termination grace period and whether the application exited before forcible termination. That is an orchestration and signal-delivery lifecycle. This article's evidence boundary is local to Python futures: queued versus running at executor shutdown.

Assert comparison invariants

The measurable comparison is:

assert cancel_case["queue-C"]["cancelled"] is True
assert keep_case["queue-C"]["cancelled"] is False

Apply the same assertion to queue-D and queue-E.

Also require:

for task in ("run-A", "run-B"):
    assert cancel_case[task]["running"] is True
    assert keep_case[task]["running"] is True

Pass condition: the only changed input, cancel_futures, changes the queued-future cancellation classification while both deliberately blocked running futures remain running at the recorded return boundary.

Fail condition: the worker-start barrier was not established, any supposedly queued task logged worker_started before shutdown, or identities cannot be reconciled.

Status: EXPECTED / NOT EXECUTED.

Exercise failure boundaries

A concurrency test is credible partly because it knows when not to issue a verdict.

The first failure boundary is insufficient control over admission to running state. CPython worker code calls Future.set_running_or_notify_cancel() before invoking the submitted callable. If that operation succeeds, the work item proceeds to the user task; if cancellation had already succeeded, execution is skipped. The fixture therefore waits for explicit worker-start records before submitting the queue-only tasks.

The second is accidental worker capacity. Changing max_workers from two to five can allow every task to start before shutdown, leaving nothing pending for cancel_futures=True to cancel. That is not evidence that cancellation is broken; it is a defective fixture for this question.

The third is sleep-based synchronization. A statement such as sleep(0.1); shutdown() guesses that workers have started. The event barrier proves it. Timing can remain in the fixture only as a bounded timeout that converts missing synchronization into HOLD rather than hanging forever.

The fourth is polluting the executor with the evidence collector. Evidence should be written by the main thread or through independent thread-safe structures. Do not submit “logger jobs” to the same two-worker pool.

The fifth is calling result() too soon. Future.result() waits for completion unless given a timeout, while cancelled futures raise CancelledError. The post-return classification should use non-blocking state accessors first.

The sixth is assuming interpreter exit proves prompt shutdown. Python specifically notes that the entire program will not exit until outstanding executor futures finish, regardless of wait. A test whose only evidence is “the process eventually terminated” has erased the boundary under test.

Any of these conditions makes the case HOLD, not ACCEPT.

Capture per-case evidence

Evidence should be append-only and keyed by both case and task. A practical JSON Lines record looks like:

{"seq": 1, "case": "cancel_pending", "kind": "worker_started", "task": "run-A"}
{"seq": 2, "case": "cancel_pending", "kind": "worker_started", "task": "run-B"}
{"seq": 3, "case": "cancel_pending", "kind": "shutdown_call", "cancel_futures": true, "wait": false}
{"seq": 4, "case": "cancel_pending", "kind": "shutdown_return"}
{"seq": 5, "case": "cancel_pending", "kind": "future_snapshot", "task": "run-A", "running": true, "cancelled": false, "done": false}
{"seq": 6, "case": "cancel_pending", "kind": "future_snapshot", "task": "queue-C", "running": false, "cancelled": true, "done": true}

Those values are illustrative schema examples only, not observed output.

Use monotonically increasing local sequence numbers as the primary ordering key. time.monotonic_ns() can be retained for diagnostics, but acceptance should not depend on a universal maximum shutdown duration. No such threshold is part of the documented shutdown(wait=False) contract.

Capture at least:

Evidence file

Purpose

baseline.txt

runtime and platform identity

expected.json

independent oracle

cancel_pending.jsonl

primary case

keep_pending.jsonl

comparison case

summary.json

reconciled classifications

decision.md

release decision and owner

The collector should write the exact Future state trio rather than a derived label only. {"state":"stopped"} is too lossy because it collapses cancellation and ordinary completion.

Use explicit task IDs instead of id(future) as durable identity. Object addresses are process-local implementation details and do not communicate business meaning to a reviewer.

Preserve failure artifacts

Pass condition: a failing assertion leaves the manifest, baseline and all events captured up to the failure point intact.

Wrap commissioning execution so cleanup occurs without deleting evidence:

set -o pipefail
python executor_shutdown_fixture.py \
  > evidence/stdout.log \
  2> evidence/stderr.log
status=$?
printf '%s\n' "$status" > evidence/exit-status.txt
exit "$status"

Do not rewrite a failed case into a clean-looking summary.

Pass: raw evidence and non-zero exit status survive together.

Fail: test automation deletes the temporary fixture before copying the failure packet, or emits only “assertion failed” without identifying case/task state.

Status: EXPECTED / NOT EXECUTED.

Reconcile state and identity

The acceptance layer should recompute outcomes from evidence rather than trusting the runner's final print statement.

For each case, create a matrix keyed by manifest task ID:

Task

Manifest class

Worker started before shutdown?

Snapshot

Terminal evidence

run-A

running

required

required

required

run-B

running

required

required

required

queue-C

cancel candidate

forbidden before return

required

required

queue-D

cancel candidate

forbidden before return

required

required

queue-E

cancel candidate

forbidden before return

required

required

“Forbidden before return” is important. A queued future that happened to begin executing before shutdown cannot validly be called a failed pending cancellation: it was no longer pending. Python's contract protects that distinction by stating that running futures are not cancelled by cancel_futures=True.

The strongest reconciliation rule is therefore:

expected-to-cancel
AND no worker_started before shutdown_return
AND cancelled=true
AND done=true
AND running=false

For an expected-running future:

worker_started before shutdown_call
AND running=true after shutdown_return
AND cancelled=false

This resembles state reconciliation in the HTTP If-Match article only at a methodological level. That page protects concurrent resource mutations by binding a client-visible validator to an atomic storage predicate and distinguishes stale writes from accepted writes. This fixture has no HTTP resource or ETag. Its reconciliation target is the correspondence among synthetic task identity, worker admission and Future lifecycle state.

If two records use the same task ID, a task appears in evidence but not the manifest, or a manifest task has no snapshot, choose HOLD.

Separate documentation from observation

A disciplined report must keep at least three evidence classes separate.

Documented behavior is what Python promises through public documentation: wait=False allows shutdown to return before outstanding work finishes; cancel_futures=True cancels work that has not started; running or completed futures are not cancelled. Future.cancel(), cancelled(), running() and done() define the externally visible state vocabulary.

Implementation explanation describes how the pinned CPython version currently achieves the behavior. In CPython 3.14.10, shutdown drains the executor's internal queue and invokes cancel() on drained futures, while it skips thread joins when wait=False. Worker execution, meanwhile, enters the running state through set_running_or_notify_cancel() before invoking user code.

Observed behavior is whatever a real commissioning run records.

This article contains no commissioning output, so its observed-behavior column is deliberately empty:

Claim

Evidence class

Article status

pending futures are eligible for cancellation

documented

VERIFIED FROM DOCS

running futures are not cancelled by shutdown

documented

VERIFIED FROM DOCS

CPython queue is drained during cancelling shutdown

implementation

VERIFIED FROM v3.14.10 SOURCE

run-A was running after return

runtime observation

EXPECTED / NOT EXECUTED

queue-C was cancelled

runtime observation

EXPECTED / NOT EXECUTED

This separation prevents an implementation detail from accidentally becoming a universal guarantee and prevents an expected test result from being written as an observation.

Define repair boundaries

A repair changes the system or fixture because a reproduced failure is understood. A rerun repeats valid test logic because evidence was lost or the environment was transiently invalid.

Examples:

Finding

Action

queued jobs actually started because fixture used five workers

REPAIR fixture

runtime was 3.14.9 instead of declared 3.14.10

RERUN after repinning

application assumes shutdown() return means no callable is active

REPAIR application contract

evidence file truncated

RERUN

documented behavior and reproducible runtime evidence disagree

HOLD and investigate

test passed but task identities cannot be reconciled

HOLD

The measurable pass condition is that every proposed change can be classified as fixture repair, application repair or evidence rerun without altering the expected manifest after seeing the result.

Status: EXPECTED / NOT EXECUTED.

Implement a bounded repair

The common application defect is not that ThreadPoolExecutor failed to honour shutdown. It is application code treating a successful shutdown call as an execution barrier.

Do not “repair” that by inserting an arbitrary delay:

executor.shutdown(cancel_futures=True, wait=False)
time.sleep(1)  # not proof

Instead choose the behavior actually required.

If the caller genuinely needs all running work to finish before proceeding, the documented primitive is wait=True:

executor.shutdown(cancel_futures=True, wait=True)

With both options true, Python documents that work already started will complete before shutdown returns and remaining pending futures will be cancelled. That is a semantic change, so it should be made deliberately rather than smuggled into a test.

If the caller needs non-blocking shutdown but explicit visibility into remaining work, retain the submitted futures and classify them:

executor.shutdown(cancel_futures=True, wait=False)

running = [
    task_id
    for task_id, future in futures.items()
    if future.running()
]

cancelled = [
    task_id
    for task_id, future in futures.items()
    if future.cancelled()
]

The repair boundary should not reach into workqueue, threads, shutdown or other private executor attributes. The CPython source is valuable for explaining implementation, but those internals are not the public acceptance API.

Also avoid attempting to cancel a known-running future and then treating False as a failure. False is the documented result when execution has already started.

A bounded repair changes only the mistaken lifecycle assumption. It does not redesign task functions, replace thread pools with asyncio, or introduce process termination mechanisms unless the actual requirement is broader than the problem stated here.

Verify rollback and rerun safety

A concurrency fixture can create its own cleanup trap. The worker blockers must always be released, including on assertion failure.

Use try/finally:

executor = ThreadPoolExecutor(max_workers=2)

try:
    # submit, establish barriers, shutdown, capture evidence
    ...
finally:
    release.set()

After releasing, reconcile every future. Cancelled futures can be recognized without calling their callable. Running futures should reach a terminal result or exception within a bounded fixture timeout. Future.result(timeout=...) provides a bounded wait and raises CancelledError for cancelled futures.

Rollback safety here means returning the disposable fixture to a state in which no synthetic task remains blocked and no evidence from one case can contaminate the next. Use a new executor, new Event, new evidence queue and new task namespace for every case.

The CSS transition cancellation article is another lifecycle-oriented neighbor. It distinguishes transitioncancel from transitionend and explicitly marks its behavioral cases EXPECTED / NOT EXECUTED when browser execution has not been supplied. Its browser event model is unrelated to Python futures, but its evidence discipline is directly compatible: expected outcomes should never masquerade as observed ones.

Reruns must preserve the original manifest. If a case fails, do not edit "queue-C": "cancelled" to "queue-C": "running" merely to make a subsequent comparison green. Change the manifest only when the acceptance contract itself changes, and retain that revision as a separate version.

Assign operational ownership

A measurable ownership table avoids the phrase “someone should investigate”:

Artifact or decision

Owner role

runtime pin

fixture maintainer

expected-case manifest

reviewer independent of runtime results

executor fixture

test author

raw evidence packet

commissioning operator

application lifecycle requirement

service owner

REPAIR implementation

owning engineering team

ACCEPT / HOLD decision

named release authority

Pass condition: every artifact and decision has an accountable role before commissioning.

Fail condition: the same person silently changes expectations after viewing runtime results without review history.

Status: EXPECTED / NOT EXECUTED.

Decide ACCEPT, REPAIR, RERUN or HOLD

The decision ledger is the final deliverable, not a green shell exit code.

Use this schema:

Case

Expected

Observed

Evidence complete?

Decision

Reason

runtime-pin

CPython 3.14.10

NOT EXECUTED

no

HOLD

commissioning absent

running-negative-control

cancel returns false

NOT EXECUTED

no

HOLD

commissioning absent

cancel-pending

two running, three cancelled

NOT EXECUTED

no

HOLD

commissioning absent

keep-pending

two running, queued work not shutdown-cancelled

NOT EXECUTED

no

HOLD

commissioning absent

reconciliation

IDs match manifest 1:1

NOT EXECUTED

no

HOLD

commissioning absent

cleanup

blockers released; cases isolated

NOT EXECUTED

no

HOLD

commissioning absent

The article-level decision is therefore HOLD. That is not a negative finding about Python. It is the only evidence-honest decision when no fixture execution is being represented as performed.

Use the four decisions consistently:

ACCEPT means all required cases were executed on the declared runtime, every manifest invariant passed, the evidence reconciles by identity, and no contradictory observation remains unexplained.

REPAIR means the evidence demonstrates a real mismatch whose cause is understood: for example, application code assumes non-blocking shutdown has stopped running callables. Apply the bounded fix and rerun the failing and comparison cases.

RERUN means the intended test remains valid but the commissioning evidence is unusable: wrong version, incomplete artifact, interrupted harness or similarly non-semantic defect.

HOLD means the available evidence cannot discriminate the relevant states, a documented contract appears to contradict reproducible runtime behavior, identity is ambiguous, or a required case has not been executed.

A practical release rule can therefore be encoded as:

if any required case is NOT EXECUTED:
    HOLD
elif any evidence is incomplete or contradictory:
    HOLD
elif fixture/environment defect invalidated a case:
    RERUN
elif understood application or fixture defect needs correction:
    REPAIR
else:
    ACCEPT

That is the release-acceptance boundary. A successful shutdown() call is merely one event inside it.

Connect the practice to Refonte Learning

This playbook is an engineering acceptance exercise: read the public contract, isolate one lifecycle boundary, construct deterministic inputs, separate the oracle from the implementation under test, preserve failure evidence, reconcile object identity, and make a bounded release decision. Those practices transfer naturally to backend development. Python's documentation and CPython's versioned source provide the technical basis for the behavior described here.

Refonte Learning's current Backend Development page identifies the offering as a Backend Developer program. The page currently lists a three-month period, 10–12 hours per week, basic programming knowledge as a requirement, and competencies including Node.js and Express, MongoDB and SQL, RESTful APIs and microservices, authentication and authorization, testing and debugging, Docker/cloud deployment and a capstone project. It also describes hands-on projects and virtual-internship-oriented experience.

Engineers who want structured practice around backend implementation and testing can review the program page; it is not evidence for ThreadPoolExecutor semantics.

For this article's fixture, the commissioning checklist remains deliberately technical:

[ ] CPython 3.14.10 pin captured
[ ] expected.json frozen before execution
[ ] running-task barrier proven
[ ] negative cancellation control captured
[ ] cancel_futures=True case captured
[ ] cancel_futures=False comparison captured
[ ] task identities reconciled
[ ] failure artifacts preserved
[ ] blockers safely released
[ ] ACCEPT / REPAIR / RERUN / HOLD signed

Every unchecked item remains EXPECTED / NOT EXECUTED. Until those records exist, the correct conclusion is not that executor shutdown failed, and not that every future stopped. It is simply that Python documents a crucial distinction: pending work may be cancelled, running work is not, and wait=False permits shutdown() to return while that running work continues.