Files
reverse-proxy/tasks/fix/inflight-counter-increment.md

2.5 KiB

id, name, status, depends_on, scope, risk, impact, level, review_findings
id name status depends_on scope risk impact level review_findings
fix/inflight-counter-increment Fix InFlightCounter to increment before spawning task (C2 + drain interval) completed
narrow medium component implementation
C2

Description

InFlightCounter::increment() is never called anywhere in the codebase. The InFlightGuard only decrements on drop. Since count stays at 0, the first guard drop does fetch_sub(1) on an AtomicUsize with value 0, which wraps to usize::MAX. is_zero() checks count == 0, which never becomes true again. The drain logic in drain_in_flight always times out.

The spec (operations.md shutdown sequence) states: "each request must increment the counter when it begins and decrement when it completes (via guard drop). The increment must happen before the request task is spawned."

Additionally, the spec states the drain polls every 100ms, but the current implementation uses 50ms. Align with the spec.

Changes Required

src/server.rs:

  • Fold the increment into InFlightGuard::new() so it's impossible to forget:
    impl InFlightGuard {
        fn new(counter: Arc<InFlightCounter>) -> Self {
            counter.increment();
            Self(counter)
        }
    }
    
  • Update serve_https_listener to use InFlightGuard::new(in_flight.clone()) instead of InFlightGuard(in_flight.clone()).
  • Make InFlightGuard's tuple struct private (if it isn't already) so callers must use new().

src/server.rsdrain_in_flight:

  • Change polling interval from 50ms to 100ms per the spec (operations.md):
    tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    

Acceptance Criteria

  • InFlightGuard::new() calls counter.increment() before returning
  • InFlightGuard is constructed via new() only, not the tuple struct
  • serve_https_listener uses InFlightGuard::new(in_flight.clone())
  • drain_in_flight polls every 100ms (not 50ms)
  • cargo test passes
  • cargo clippy passes with no warnings

References

  • docs/architecture/operations.md — shutdown sequence, in-flight counter
  • docs/reviews/003-security-and-bug-review.md — C2 finding
  • src/server.rs — InFlightCounter, InFlightGuard, drain_in_flight
  • src/main.rs — drain_in_flight caller

Notes

The previous fix/graceful-shutdown task addressed the abort-vs-join logic but did not fix the increment bug. This task completes that work.

Summary

To be filled on completion