Refuse blocks once the block processor stops and drop the queued ones (#5263) * Refuse blocks once the block processor stops and drop the queued ones A blocking add queued its block and waited on the result promise with no timeout. After stop () nothing processes the queue, and the queued context kept the promise alive, so the caller waited until the processor was destroyed. node::stop () stops the block processor before the wallets, so a wallet receive that reached process_local () in that window blocked the wallet action thread, wallets::stop () never got its join back, and the node hung on shutdown. node.rep_self_vote hit it on CI: its block0 confirms, and the wallet auto-receives it while the test tears down. add_impl now checks `stopped` under the lock its pushes take and refuses the block once it is set, and stop () drops whatever is still queued after joining the thread. A blocking add's block is either refused or queued before the drop, so the add always gets a result or a broken promise and returns nullopt. Both are counted as `stopped`. Batch adds keep their own path unchanged: nothing waits on them, so a batch queued after stop () only sits there until the processor is destroyed, as before. block_processor.size_per_channel froze the queue by stopping the processor and adding afterwards, which a stopped processor now refuses. It runs on a processor that is never started instead. Against the previous implementation add_after_stop fails at its first assertion, add () accepting the block, and add_blocking_released_on_stop times out waiting for the blocked add to return. * Drop the ledger notifications still queued when they stop Processed block contexts, with the result promises of blocking adds, are completed on the ledger notifications thread. A notification still queued when that thread exited kept its promises pending until the component was destroyed, the same wait the block processor's queue caused one step earlier. stop () now drops the queue after joining the thread, counted as `stopped`. The block processor is the only source of processed notifications and stops first, so nothing queues one after the drop. Against the previous implementation stop_drops_queued fails: the promise is still pending after stop ().
__________
Type: commit
Hash: 7d8e31cdd7c8483f2cbb1d5cfffa97d6bce188aa
Created: yesterday
__________
gr0v1ty/nano-node:7d8e31cdd7c8483f2cbb1d5cfffa97d6bce188aa
| Test Case | Status | Duration | Median Deviation | Log | Graph |
|---|---|---|---|---|---|
| 5n4pr_conf_10k_bintree | PASS | 106 s | -4.5 s | GitHub job logs | Show |
| 5n4pr_conf_10k_change | PASS | 175 s | 42.0 s | GitHub job logs | Show |
| 5n4pr_conf_change_dependant | PASS | 109 s | -6.5 s | GitHub job logs | - |
| 5n4pr_conf_change_independant | PASS | 107 s | -6.0 s | GitHub job logs | - |
| 5n4pr_conf_send_dependant | PASS | 108 s | -6.0 s | GitHub job logs | - |
| 5n4pr_conf_send_independant | PASS | 110 s | -2.0 s | GitHub job logs | - |
| 5n4pr_rocks_10k_bintree | PASS | 109 s | -3.0 s | GitHub job logs | - |
| 5n4pr_rocks_10k_change | PASS | 160 s | 2.5 s | GitHub job logs | - |