Skip to content

Track Windows Lyrical CI crash from upstream class_loader concurrent unload race #63

Open

Description

@noelex

Summary

Track an intermittent native crash in the Windows ROS Lyrical / Fast DDS CI job, consistent with the upstream class_loader concurrent library unload bug fixed by ros/class_loader#234.

Temporary triage policy: CI failures matching the signature below are a known upstream dependency issue and may be ignored until the dependency is updated. This applies only to this specific crash signature, not to other failures in the same job or test.

Observed failure

The test host terminates with:

Fatal error. System.AccessViolationException:
Attempted to read or write protected memory.

at Rcl.Interop.RclCommon.rcl_shutdown(rcl_context_t*)
at Rcl.SafeHandles.SafeContextHandle.Shutdown()
at Rcl.RclContext+<>c__DisplayClass77_0.<Run>b__2()
at Rcl.RclContext+<>c__DisplayClass77_0.<Run>g__Attempt|0(System.Action)
at Rcl.RclContext.Run()

The .NET 8 run was aborted after 285 passed tests and 1 skipped test. The later .NET 9 and .NET 10 runs in the same job succeeded. The final MSB4181 is a consequence of the test-host crash, not the primary failure. All 11 other matrix jobs passed.

Dump analysis

Artifact: windows-lyrical-test-diagnostics (the workflow retains diagnostics for only 7 days).

Files include:

  • Sequence_73e9349496674b9eb6f545aba1bbb11d.xml
  • testhost.exe_7768_1790609109_crashdump.dmp

The dump and matching DLLs from the configured Windows ROS archive show:

  • The faulting thread is unloading buffer backend plugins through rosidl_buffer_backend_registry, class_loader, and rcpputils::SharedLibrary::unload_library().
  • The immediate failure is inside rcutils_unload_shared_library, at the indirect call to lib->allocator.deallocate(lib->library_path, lib->allocator.state).
  • The saved fault context has RIP = 0 and RAX = 0; the return address is rcutils.dll + 0xde06, immediately after call rax at offset 0xde04.
  • The referenced rcutils_shared_library_t is entirely zeroed, including its deallocator function pointer. This is consistent with overlapping unload operations on shared library state.

This strongly matches the upstream race, but the fix has not yet been validated against this CI failure. There is no evidence tying the crash to PR #62's graph snapshot changes.

Upstream status and affected dependency

This is not inherently Windows-only: the upstream report reproduces the race on Linux/Jazzy. Ubuntu passing this run does not establish immunity; its installed class_loader version was not verified.

Follow-up when an upstream Windows package is available

  • Check the next official Windows Lyrical archive and confirm it contains class_loader 3.0.2 or the equivalent backported fix; a newer archive date alone is insufficient.
  • Update the Windows Lyrical archive URL in .github/workflows/test.yml and ensure the ROS installation cache does not reuse the old package.
  • Re-run the Windows Lyrical / Fast DDS tests across .NET 8, 9, and 10, including repeated runs of the concurrent-context shutdown test.
  • Remove the temporary known-failure exception and close this issue after verification.

Until then, matching failures can be left without a code change or repeated reruns solely to obtain a green result. Different crash locations, assertion failures, and other CI errors still require investigation. Keep the test enabled so the eventual dependency update can be validated.

Activity

  1. noelex commented on Oct 8, 2026

    @noelex
    OwnerAuthor

    Another occurrence affecting PR #64 (Add loaned message support and fix action buffer lifetimes), at commit 781b72c:

    • Failed job: Windows Lyrical / Fast DDS, October 8, 2026.
    • This time the .NET 10 test host crashed with 0xC0000005; the .NET 8 and .NET 9 runs passed.
    • Active test: ShutdownLifecycleTests.RetainedChildrenKeepEachPhysicalContextsLoggingReference.
    • Dump analysis confirms the same signature documented above: rcl_shutdown -> rmw_shutdown -> buffer backend registry teardown -> class_loader -> rcutils_unload_shared_library, with a null deallocator call and return address rcutils.dll + 0xde06.

    This matches the known upstream failure tracked here and falls under the existing temporary triage policy. The reference records an affected PR, not evidence that its changes introduced the crash.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions