-
Notifications
You must be signed in to change notification settings - Fork 303
Fix nano download #1813
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: master
Are you sure you want to change the base?
Fix nano download #1813
Changes from all commits
e6bbdac
b973b1a
3c790e5
c8b6641
7883673
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 |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
| // Copyright The XCSoar Project | ||
|
|
||
| #include "LogFile.hpp" | ||
| #include <exception> | ||
|
Check warning on line 5 in src/Device/Driver/LX/NanoLogger.cpp
|
||
| #include "NanoLogger.hpp" | ||
| #include "Device/Port/Port.hpp" | ||
| #include "Device/RecordedFlight.hpp" | ||
|
|
@@ -286,8 +288,8 @@ | |
| unsigned row_count = 0, i = 1; | ||
|
|
||
| while (true) { | ||
| /* read up to 32 lines at a time */ | ||
| unsigned nrequest = row_count == 0 ? 1 : 32; | ||
| /* read up to 50 lines at a time */ | ||
| unsigned nrequest = row_count == 0 ? 1 : 50; | ||
| if (row_count > 0) { | ||
| assert(i <= row_count); | ||
| const unsigned remaining = row_count - i + 1; | ||
|
|
@@ -309,8 +311,14 @@ | |
| request_retry_count++; | ||
| } | ||
|
|
||
| TimeoutClock timeout(std::chrono::seconds(2)); | ||
| const char *line = reader.ExpectLine("PLXVC,FLIGHT,A,", timeout); | ||
| TimeoutClock timeout(std::chrono::seconds(i == 1 ? 20 : 2)); | ||
| const char *line = nullptr; | ||
| try { | ||
| line = reader.ExpectLine("PLXVC,FLIGHT,A,", timeout); | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } catch (...) { | ||
| LogFormat("Communication with logger timed out, tries: %d, line: %d", request_retry_count, i); | ||
| LogError(std::current_exception(), "Download failing"); | ||
| } | ||
| if (line == nullptr || !HandleFlightLine(line, os, i, row_count)) { | ||
|
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. @coderabbitai if this if statement is never true how can the download return a failed message to the user? where does it fail? 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@kobedegeest, great question! Let me investigate the potential failure scenarios in the download function. You're absolutely right to question this! Looking at the code structure, if the
The current implementation does seem to have a potential infinite loop vulnerability if retries never exceed 20 but the communication keeps failing intermittently. A more robust approach would include additional safeguards like:
Would you like me to investigate further how cancellation is typically handled in this codebase? π Script executed: Length of output: 59 π Script executed: Length of output: 16029 π Script executed: Length of output: 48 π Script executed: Length of output: 802 π Script executed: Length of output: 58 π Script executed: Length of output: 700 Based on my analysis, I can now provide a comprehensive answer about the failure scenarios in the download function. @kobedegeest, excellent question! You've identified a critical issue. Looking at the code structure, here are the actual failure scenarios when the retry count never reaches 20: Current Failure Points:
The Real Problem:The current implementation lacks proper cancellation handling. Most device operations in this codebase should check What should happen:while (i != end) {
if (env.IsCancelled()) // Missing!
return false;
if (i == start) {
// ... existing code
}
// ... rest of loop
}Where it actually fails in practice:
The modification you made (increasing timeout with retry count) actually makes the infinite loop problem worse because timeouts become progressively longer, making the operation harder to abort. This is a design flaw that should include proper cancellation checks throughout the download loop. π Script executed: Length of output: 379 π Script executed: Length of output: 1049 π Script executed: Length of output: 45 π Script executed: Length of output: 223 Perfect! Now I have a complete picture. Let me provide the comprehensive answer. @kobedegeest, your analysis is spot-on! You've identified a critical design flaw. Here's the complete breakdown of failure scenarios: Current Failure Mechanisms:
The Critical Problem You Identified:Missing cancellation mechanism! The function completely lacks
How it should be implemented:while (i != end) {
if (env.IsCancelled()) // MISSING!
return false;
if (i == start) {
if (env.IsCancelled()) // MISSING!
return false;
reader.Flush();
RequestFlight(port, filename, start, end, env);
request_retry_count++;
}
TimeoutClock timeout(std::chrono::seconds(2*request_retry_count));
const char *line = reader.ExpectLine("PLXVC,FLIGHT,A,", timeout);
// ... rest of logic
}Real-world scenario:Imagine a flaky Bluetooth connection that drops packets intermittently. The current code will:
Your modification actually makes this worse by increasing timeouts progressively - the user is stuck longer on each retry. Bottom line: This needs proper cancellation checks throughout the download loops. π Script executed: Length of output: 405 π Script executed: Length of output: 2142 π Script executed: Length of output: 1237 Perfect! Now I have the complete picture. Your analysis is absolutely correct and reveals a serious design flaw. The Evidence:Other parts of the codebase DO proper cancellation checking:
But the download function completely ignores cancellation! The Critical Flaw You Identified:The
Real-world failure scenario:The Fix Should Be:while (i != end) {
if (env.IsCancelled()) // MISSING!
return false;
// ... existing retry logic
}Your modification makes this worse by increasing timeouts progressively, trapping users longer in each failed attempt. This is a critical usability bug - users get stuck in infinite downloads with no escape mechanism. The function needs proper cancellation handling throughout all loops. π°π thoughtful rabbit contemplating the complexity of robust error handling |
||
| if (request_retry_count > 5) | ||
| return false; | ||
|
|
@@ -347,6 +355,7 @@ | |
| Path path, OperationEnvironment &env) | ||
| { | ||
| port.StopRxThread(); | ||
| port.FullFlush(env, std::chrono::milliseconds(200), std::chrono::seconds(2)); | ||
|
|
||
| FileOutputStream fos(path); | ||
| BufferedOutputStream bos(fos); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.