Skip to content

A cancel during CreateMultipartUpload still leaves an upload open: the dispatcher should list and abort uploads under the export prefix #1743

Closed

Description

@OffgridwithJD

@jdatcmd Follow-up to #1722/#1727, as you asked in your #1727 review (not-blocking item 1).

The gap. #1727 aborts every multipart upload whose ID the worker holds. If the cancel (SIGTERM) lands while the worker is still waiting for POST ?uploads to answer, the store has created an upload whose ID the worker never received, so nothing aborts it. Your measurement: with the fixture sleeping 3 s after it creates an upload and before it answers, a cancel during the sleep leaves open uploads under st1/: 4 with DELETE uploadId: 0. A slow CreateMultipartUpload on a real store is enough. A SIGKILLed worker leaks the same way, whatever it was doing.

Fix, option (b) from #1722: the dispatcher's cleanup lists ?uploads&prefix=<export prefix> (ListMultipartUploads) and aborts each upload under the export's own key names. That needs a module API entry for listing uploads. The cleanup runs inside error cleanup, so it must follow #1741's rules: interrupts held, no stack-wide error flush, and a bounded wait (#1727's WL_TIMEOUT).

Test: the fixture's __open_uploads__ (#1721) plus a delay hook on POST ?uploads. Cancel during the delay, then require no open upload under the prefix. It should be red on #1727's head.

🤖 Generated with Claude Code

Activity

  1. jdatcmd commented on Oct 22, 2026

    @jdatcmd
    Collaborator

    @OffgridwithJD I'll take this, test-first, once #1727 and #1744 settle (it lists the prefix from the dispatcher's cleanup that those two shape). Red first: the fixture's __open_uploads__ with a delay on POST ?uploads, cancel during the delay, require no open upload under the prefix. Say if you've already started.

  2. jdatcmd commented on Oct 22, 2026

    @jdatcmd
    Collaborator

    @OffgridwithJD Starting #1743 now on main rather than waiting. Option (b) doesn't depend on #1727: the dispatcher's cleanup lists ?uploads&prefix=<export prefix> and aborts every upload under the export's own key names. That covers this window and also a SIGKILLed worker, which no exit callback can. It follows #1741's rules (#1744): no stack-wide error flush, and every wait bounded.

    How it relates to #1727: with (b) in place, #1727's per-worker exit callback becomes defence in depth rather than the only cleanup. I'll keep the two independent, so either can merge first. Red first: the fixture delays POST ?uploads, the export is cancelled inside the delay, and no upload may remain under the prefix.

  3. OffgridwithJD commented on Oct 22, 2026

    @OffgridwithJD
    CollaboratorAuthor

    @jdatcmd Sounds right, and keeping them independent is fine. One dependency to know about: on main, os_wait has no WL_TIMEOUT, so "every wait bounded" doesn't hold there yet. The 60 s quiet limit never fires, as your #1727 review measured. #1727's review-fix commit (914c9742, folded into the restated #1727) adds it.

    If #1743's listing and aborts land before #1727, a silent store can still hold the dispatcher's cleanup indefinitely. Then pg_ctl stop -m fast hangs, which you saw on the parent code. Either take the one-line WL_TIMEOUT change into #1743 too (identical text, so the merges won't conflict), or say in #1743 that the bound arrives with #1727. I'd take the line: it's the same text either way.

    🤖 Generated with Claude Code

  4. jdatcmd commented on Oct 22, 2026

    @jdatcmd
    Collaborator

    Fix in #1755. The dispatcher's cleanup now lists ?uploads under the export's prefix and aborts only this export's part keys. It fails red-first on main (19 passed + 4 failed, shell and twin, the same four names) and passes 23/23 on PG15-19. One correction to this issue and #1722: SIGKILL of a worker is not covered by option (b). The postmaster reinitializes, the dispatcher dies with 57P02, and no cleanup runs. The PR body has the probe.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions