Skip to content

Follow-ups from #744: parallel driver closes at shutdown, onClose no longer tied to the fd's map removal #763

Description

@FumingPower3925

The review of #744 (celeris#735) left these minor findings and nits. The review's blocking finding, a test that could pass without the close lingering, is fixed on the branch (2948301). The items below were left for later, and each says what to do.

1. Shutdown still closes lingering driver sockets one after another, on the worker (nit)

shutdownDrivers closes each registered conn's engine descriptor on the worker goroutine, in a loop (engine/iouring/driver.go at 782f435, the for _, dc := range conns loop: if dc.retire() { _ = unix.Close(dc.opFD) }; dc.fireOnClose(errEngineShutdown)).

  • With N lingering sockets, engine stop takes up to N × linger.
  • waitDriverCloses then adds the longest linger among the closes that were handed off before shutdown.
  • Engine.Shutdown ignores its ctx (engine.go:460), and Listen waits for the workers (engine.go:384), so a stop waits out every linger.

main has the same serial close (retire closed on the worker), so this is not a regression.

To do: hand these closes to closeOpFD-style goroutines and let the existing wait cover them, so they run in parallel. onClose must still fire after its close.

2. onClose is no longer tied to the map removal (nit, a documented hazard for third-party drivers)

Since #744, onClose fires at least one loop iteration after finalizeDriver, because it takes a goroutine and a driver-action round trip. It is no longer tied to the conn leaving driverConns. So a RegisterConn of the same caller fd number can succeed before the old conn's onClose runs.

  • engine/provider.go documents this ("fails ... until the conn is finalized, which is at the latest when onClose fires").
  • The in-tree drivers keep per-conn closures (driver/redis/conn.go:292, driver/postgres/conn.go:886, driver/memcached/conn.go:211), not fd-keyed state, so nothing in-tree is affected.
  • A third-party driver that keys its state by fd and deletes that state in onClose could delete the new conn's entry.

To do: either say so explicitly in the RegisterConn/UnregisterConn docs ("do not key onClose state by fd number"), or pass onClose something that identifies the registration and not only the number.

3. Items the round-2 push dealt with (for the record)

  • The body's round-1 diagnosis (minor). There were two causes, not one. CI job 108681501232 failed in 0.12 s because the close did not linger (the shallow rig, fixed by 5f3593c). The local 3.1 s failures were an ordering race (fixed by 1d83906). The PR body now says so.
  • Evidence hygiene (nit). Lint is now taken at the head. The combined three-PR merge claim now has a saved script. The mislabelled round-1 log is noted in the lane README.

To do: nothing further.

4. The shutdown test syncs on a 200 ms sleep (minor, CodeRabbit on 2948301)

From the CodeRabbit review of #744 (#744 (comment)). TestDriverShutdownWaitsForAHandedOffClose (engine/iouring/driver_linger_close_linux_test.go, lines 284-289 at 2948301) starts stop() on a goroutine, sleeps 200 ms, then calls drain(). The sleep does not prove the worker reached waitDriverCloses before the close returned.

  • If the stop is slower than 200 ms, the close returns first, the worker's loop fires onClose, and waitDriverCloses finds nothing to wait for. The test then passes without exercising the shutdown wait. It cannot fail falsely.
  • driversClosed is set before shutdownDrivers returns, so polling it would not prove the wait has started either; an open stopped channel only proves the stop has not finished.
  • The M2 control (no waitDriverCloses) was killed 3/3 in m8, so the test does exercise the wait on that shape. The risk is a vacuous pass on a slow runner.

To do: add a test-only hook that fires when waitDriverCloses starts (no production behavior change), wait for it with a deadline before drain(), and rerun the M2 control.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/driverDatabase/cache driver infrastructurearea/engineEngine interface or implementationengine/iouringio_uring engine specificsenhancementNew feature or requestplatform/linuxLinux-specific (io_uring, epoll)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions