1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-08 19:46:02 +01:00

fix(libstore/filetransfer): prevent double callback invocation on interrupt during retry

Fix a race condition where interrupting a download (via Ctrl-C) during a
retry attempt could cause a crash. When `enqueueItem()` throws because the
download thread is shutting down, the exception would propagate without
setting `done=true`, causing the `TransferItem` destructor to invoke the
callback a second time.

This triggered an assertion failure in `Callback::rethrow()` with:
`Assertion '!prev' failed` and the error message `cannot enqueue download
request because the download thread is shutting down`.

The fix catches the exception from `enqueueItem()` and calls `fail()` to
properly complete the transfer, ensuring the callback is invoked exactly
once.
This commit is contained in:
Bernardo Meurer Costa 2025-10-29 18:08:17 +00:00
parent da637a05da
commit 560a596de7
No known key found for this signature in database

View file

@ -598,7 +598,14 @@ struct curlFileTransfer : public FileTransfer
decompressionSink.reset();
errorSink.reset();
embargo = std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
try {
fileTransfer.enqueueItem(shared_from_this());
} catch (const nix::Error & e) {
// If enqueue fails (e.g., during shutdown), fail the transfer properly
// instead of letting the exception propagate, which would leave done=false
// and cause the destructor to attempt a second callback invocation
fail(std::move(exc));
}
} else
fail(std::move(exc));
}