-
Notifications
You must be signed in to change notification settings - Fork 8
filetransfer: handle exceptions thrown from enqueueItem #348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -962,19 +962,32 @@ struct curlFileTransfer : public FileTransfer | |
| writeFull(wakeupPipe.writeSide.get(), " "); | ||
| #endif | ||
|
|
||
| return ItemHandle(static_cast<Item &>(*item)); | ||
| return ItemHandle(ref<Item>(std::move(item))); | ||
| } | ||
|
|
||
| ItemHandle enqueueFileTransfer(const FileTransferRequest & request, Callback<FileTransferResult> callback) override | ||
| ItemHandle | ||
| enqueueFileTransfer(const FileTransferRequest & request, Callback<FileTransferResult> callback) noexcept override | ||
| { | ||
| /* Handle s3:// URIs by converting to HTTPS and optionally adding auth */ | ||
| if (request.uri.scheme() == "s3") { | ||
| auto modifiedRequest = request; | ||
| modifiedRequest.setupForS3(); | ||
| return enqueueItem(make_ref<TransferItem>(*this, std::move(modifiedRequest), std::move(callback))); | ||
| auto item = make_ref<TransferItem>(*this, std::move(modifiedRequest), std::move(callback)); | ||
| try { | ||
| return enqueueItem(item); | ||
| } catch (const nix::Error & e) { | ||
| item->fail(e); | ||
| return ItemHandle(ref<Item>(std::move(item))); | ||
| } | ||
| } | ||
|
|
||
| return enqueueItem(make_ref<TransferItem>(*this, request, std::move(callback))); | ||
| auto item = make_ref<TransferItem>(*this, request, std::move(callback)); | ||
| try { | ||
| return enqueueItem(item); | ||
| } catch (const nix::Error & e) { | ||
| item->fail(e); | ||
| return ItemHandle(ref<Item>(std::move(item))); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a lot of repetition. Maybe this function should be refactored? It compiles, but please don't trust my choices about naming and inlining too much. |
||
| } | ||
|
Comment on lines
+968
to
991
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's look at the actual function in the file to confirm its current state
head -1000 src/libstore/filetransfer.cc | tail -100Repository: DeterminateSystems/nix-src Length of output: 3430 🏁 Script executed: # Check if setupForS3 can throw nix::Error
rg -n 'setupForS3' --type cpp -B 2 -A 10Repository: DeterminateSystems/nix-src Length of output: 6673 🏁 Script executed: # Check for throw statements in s3-related code
rg -n 'throw' --type cpp -g '*s3*' | head -30Repository: DeterminateSystems/nix-src Length of output: 1282 🏁 Script executed: # Look for ParsedS3URL::parse implementation
rg -n 'ParsedS3URL::parse' --type cpp -B 2 -A 15Repository: DeterminateSystems/nix-src Length of output: 7084 🏁 Script executed: # Check if TransferItem constructor can throw
rg -n 'struct TransferItem\|class TransferItem' --type cpp -A 20Repository: DeterminateSystems/nix-src Length of output: 52
The function is marked
If any of these throw, 🛠️ Suggested fix: wrap entire body in try-catch ItemHandle
enqueueFileTransfer(const FileTransferRequest & request, Callback<FileTransferResult> callback) noexcept override
{
+ try {
/* Handle s3:// URIs by converting to HTTPS and optionally adding auth */
if (request.uri.scheme() == "s3") {
auto modifiedRequest = request;
modifiedRequest.setupForS3();
auto item = make_ref<TransferItem>(*this, std::move(modifiedRequest), std::move(callback));
- try {
- return enqueueItem(item);
- } catch (const nix::Error & e) {
- item->fail(e);
- return ItemHandle(ref<Item>(std::move(item)));
- }
+ return enqueueItem(item);
}
auto item = make_ref<TransferItem>(*this, request, std::move(callback));
- try {
- return enqueueItem(item);
- } catch (const nix::Error & e) {
- item->fail(e);
- return ItemHandle(ref<Item>(std::move(item)));
+ return enqueueItem(item);
+ } catch (const nix::Error & e) {
+ // Need to handle the case where item doesn't exist yet
+ // This requires restructuring to ensure item is always created first
+ // or using a different error reporting mechanism
}
}Note: A complete fix requires restructuring to handle exceptions that occur before the 🤖 Prompt for AI Agents |
||
|
|
||
| void unpauseTransfer(ref<TransferItem> item) | ||
|
|
@@ -988,7 +1001,7 @@ struct curlFileTransfer : public FileTransfer | |
|
|
||
| void unpauseTransfer(ItemHandle handle) override | ||
| { | ||
| unpauseTransfer(ref{static_cast<TransferItem &>(handle.item.get()).shared_from_this()}); | ||
| unpauseTransfer(ref{static_cast<TransferItem &>(*handle.item).shared_from_this()}); | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -1047,7 +1060,7 @@ void FileTransferRequest::setupForS3() | |
| #endif | ||
| } | ||
|
|
||
| std::future<FileTransferResult> FileTransfer::enqueueFileTransfer(const FileTransferRequest & request) | ||
| std::future<FileTransferResult> FileTransfer::enqueueFileTransfer(const FileTransferRequest & request) noexcept | ||
| { | ||
| auto promise = std::make_shared<std::promise<FileTransferResult>>(); | ||
| enqueueFileTransfer(request, {[promise](std::future<FileTransferResult> fut) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was suggested that I move this try-catch into
enqueueItemdirectly, but I decided not to do that because I didn't want to mess with the fix in NixOS#14418I tried a few different ways to reduce the duplication, but I couldn't figure out the best way to do that.
ref<TransferItem> item;outside of theifdoesn't work because there's no constructor, and I didn't want to copyrequestevery time in the off chance that it's an s3 request...Happy to take suggestions on improvements here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see my comment below (I should have posted it here). Refactoring is definitely doable if
itemis initialized once and unconditionally, meaning that its value should come from another function (make it inline if you want). No new copying is needed, the request is passed by reference and the callback is moved.