Skip to content

Fix Docker timestamp fractional seconds, snprintf buffer bug, LxtLogError args, and misc code/script cleanup#40489

Closed
Copilot wants to merge 2 commits into
masterfrom
copilot/fix-docker-timestamp-parsing
Closed

Fix Docker timestamp fractional seconds, snprintf buffer bug, LxtLogError args, and misc code/script cleanup#40489
Copilot wants to merge 2 commits into
masterfrom
copilot/fix-docker-timestamp-parsing

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 10, 2026

Multiple correctness bugs and code quality issues across WSLCContainer, WSLCSession, lxtfs tests, and tooling scripts.

Summary of the Pull Request

Fixes a timestamp parsing failure for Docker ISO 8601 timestamps with fractional seconds, a snprintf buffer size mismatch (potential overflow), missing format arguments in LxtLogError, and several code clarity/correctness issues in PowerShell scripts.

PR Checklist

  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

WSLCContainer.cpp

  • ParseDockerTimestamp: %FT%H:%M:%S%Z fails on fractional seconds (e.g. 2026-03-05T10:30:00.123456789Z). Now strips the fractional part before parsing, handling Z, +, and - timezone offsets correctly.
  • waitForStop: Extract isKillSignal named bool for clarity; removes the opaque one-liner.
  • Comment typos: "Passed this point" → "Past this point"; "can be bind" → "can bind".

WSLCSession.cpp

  • IndentLines: Replaced manual index+bounds loop with iterator + std::next().
  • c_dockerdReadyLogLine: Moved from inside OnProcessLog (called on every log line) to file scope.
  • c_logId: Moved from static constexpr inside a lambda to constexpr auto at function scope; style now matches other file-scope constants.
  • std::accumulate: Removed redundant explicit template args; init value changed to size_t{0} (type-safe).

test/linux/unit_tests/lxtfs.c

  • snprintf buffer bug: snprintf(ExpectedCombinedOptions, sizeof(ExpectedOptions), ...) used the wrong size — corrected to sizeof(ExpectedCombinedOptions).
  • LxtLogError args: Format string "%lld.%.9ld not greater than %lld.%.9ld" was passed struct pointers instead of the four tv_sec/tv_nsec members — now passes Timestamp1->tv_sec, Timestamp1->tv_nsec, Timestamp2->tv_sec, Timestamp2->tv_nsec with correct casts.
  • Minor comment spelling: "afer" → "after", "pa value" → "value".

tools/setup-dev-env.ps1

  • Added Test-Path guard on $configPath before calling winget configure; surfaces a clear error instead of a cryptic winget failure when the config file is missing.
  • Error message now references $configPath (full path) instead of $configFile.

tools/test/run-tests.ps1

  • Parameter doc: default listed as .\wsl.msix but actual default is .\installer.msix.
  • Exit check: !$?$LASTEXITCODE -ne 0; exit propagates $LASTEXITCODE instead of hardcoded 1.

Validation Steps Performed

  • Code review of all diffs against original source for correctness.
  • snprintf and LxtLogError fixes verified against their variable declarations in context.
Original prompt
Please apply the following diffs and create a pull request.
Once the PR is ready, give it a title based on the messages of the fixes being applied.

[{"message":"The format string \"%FT%H:%M:%S%Z\" does not account for fractional seconds in Docker timestamps (e.g., \"2026-03-05T10:30:00.123456789Z\"). This will cause parsing to fail or produce incorrect results. Consider using a more robust parsing approach that handles the fractional seconds component, or strip the fractional part before parsing.","fixFiles":[{"filePath":"src/windows/wslcsession/WSLCContainer.cpp","diff":"diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp\n--- a/src/windows/wslcsession/WSLCContainer.cpp\n+++ b/src/windows/wslcsession/WSLCContainer.cpp\n@@ -306,8 +306,41 @@\n std::uint64_t ParseDockerTimestamp(const std::string& timestamp)\n {\n     // Docker timestamps are UTC ISO 8601, e.g. \"2026-03-05T10:30:00.123456789Z\".\n+    // This function returns epoch seconds, so strip optional fractional seconds before parsing.\n+    std::string normalizedTimestamp = timestamp;\n+\n+    const auto timeSeparator = normalizedTimestamp.find('T');\n+    if (timeSeparator != std::string::npos)\n+    {\n+        const auto fractionalSeparator = normalizedTimestamp.find('.', timeSeparator + 1);\n+        const auto zuluPos = normalizedTimestamp.find('Z', timeSeparator + 1);\n+        const auto plusOffsetPos = normalizedTimestamp.find('+', timeSeparator + 1);\n+        const auto minusOffsetPos = normalizedTimestamp.find('-', timeSeparator + 1);\n+\n+        auto timezonePos = std::string::npos;\n+        if (zuluPos != std::string::npos)\n+        {\n+            timezonePos = zuluPos;\n+        }\n+        if (plusOffsetPos != std::string::npos && (timezonePos == std::string::npos || plusOffsetPos < timezonePos))\n+        {\n+            timezonePos = plusOffsetPos;\n+        }\n+        if (minusOffsetPos != std::string::npos && (timezonePos == std::string::npos || minusOffsetPos < timezonePos))\n+        {\n+            timezonePos = minusOffsetPos;\n+        }\n+\n+        if (fractionalSeparator != std::string::npos && (timezonePos == std::string::npos || fractionalSeparator < timezonePos))\n+        {\n+            normalizedTimestamp.erase(\n+                fractionalSeparator,\n+                (timezonePos == std::string::npos) ? std::string::npos : (timezonePos - fractionalSeparator));\n+        }\n+    }\n+\n     std::chrono::sys_seconds utcSeconds;\n-    std::istringstream stream(timestamp);\n+    std::istringstream stream(normalizedTimestamp);\n     stream >> std::chrono::parse(\"%FT%H:%M:%S%Z\", utcSeconds);\n     THROW_HR_IF_MSG(E_INVALIDARG, stream.fail(), \"Failed to parse timestamp '%hs'\", timestamp.c_str());\n \n"}]},{"message":"The logic for determining whether to wait for stop is complex and could be clearer. When Kill is true but Signal is not SIGKILL, waitForStop becomes false, which may not be immediately obvious. Consider adding a comment explaining this logic or refactoring to make the intention more explicit.","fixFiles":[{"filePath":"src/windows/wslcsession/WSLCContainer.cpp","diff":"diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp\n--- a/src/windows/wslcsession/WSLCContainer.cpp\n+++ b/src/windows/wslcsession/WSLCContainer.cpp\n@@ -825,7 +825,10 @@\n \n     // Don't wait for the container to stop if we're not sending SIGKILL, since it may not stop the container.\n     // N.B. If the signal was SIGTERM for instance, we'll receive the stop notification via OnEvent().\n-    bool waitForStop = !Kill || (SignalArg.value_or(WSLCSignalSIGKILL) == WSLCSignalSIGKILL);\n+    // When Kill is true but the requested signal is not SIGKILL, do not wait synchronously for stop.\n+    const bool isKillSignal = (SignalArg.value_or(WSLCSignalSIGKILL) == WSLCSignalSIGKILL);\n+    const bool shouldWaitWhenKill = isKillSignal;\n+    const bool waitForStop = !Kill || shouldWaitWhenKill;\n \n     try\n     {\n"}]},{"message":"Typo in comment. Change \"Passed this point\" to \"Past this point\".","fixFiles":[{"filePath":"src/windows/wslcsession/WSLCContainer.cpp","diff":"diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp\n--- a/src/windows/wslcsession/WSLCContainer.cpp\n+++ b/src/windows/wslcsession/WSLCContainer.cpp\n@@ -978,7 +978,7 @@\n     }\n \n     // Release the lock so the container can still be interacted with while the export is in progress.\n-    // Passed this point, no member variables can be accessed.\n+    // Past this point, no member variables can be accessed.\n     lock.reset();\n \n     io.Run({});\n"}]},{"message":"Grammar error in comment. Change \"can be bind\" to \"can bind\".","fixFiles":[{"filePath":"src/windows/wslcsession/WSLCContainer.cpp","diff":"diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp\n--- a/src/w...

Copilot AI requested review from Copilot and removed request for Copilot May 10, 2026 23:21
Copilot AI requested review from Copilot and removed request for Copilot May 10, 2026 23:28
Copilot AI changed the title [WIP] Fix Docker timestamp parsing for fractional seconds Fix Docker timestamp fractional seconds, snprintf buffer bug, LxtLogError args, and misc code/script cleanup May 10, 2026
Copilot AI requested a review from benhillis May 10, 2026 23:29
@benhillis
Copy link
Copy Markdown
Member

@copilot - I think this should be split into separate prs for each change.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 11, 2026

@benhillis I've opened a new pull request, #40492, to work on those changes. Once the pull request is ready, I'll request review from you.

@benhillis
Copy link
Copy Markdown
Member

Closing in favor of the split-out, focused PRs:

@benhillis benhillis closed this May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants