Skip to content

[TEST][RUST] Register the reflection test types before any test reads… - #862

Merged
tqchen merged 1 commit into
apache:mainfrom
Seven-Streams:main-dev/2026-10-21/rust-reflection-test-race
Oct 22, 2026
Merged

tqchen merged 1 commit into
apache:mainfrom
Seven-Streams:main-dev/2026-10-21/rust-reflection-test-race

Conversation

@Seven-Streams

Copy link
Copy Markdown
Member

Summary

Fix a flaky crash in the Rust test test_object_reflection (added in #859).
It failed the Windows job of the main CI run
39440570092:

Exception caught during TVMFFIGetTypeInfo:
Check failed: (entry != nullptr) is false: Cannot find type info for type_index=139

Cause

#[type_register] types register on first use. In test_object_reflection.rs
that first use happens inside the tests, which cargo runs on several threads,
so one test registers a type while another reads the type table
(TVMFFIGetTypeInfo, is_instance_of, ffi.StructuralEqual, ...).

TYPE_REGISTRATION keeps registrations from running at the same time, but it
does not block readers, and the runtime does not lock its type table. Each
type registered in the dynamic range grows type_table_ (src/ffi/object.cc):
the vector reallocates, moves every entry out of the old buffer and frees it.
A reader still on the old buffer sees a null entry (the error above, after
which the process exits) or freed memory (a segfault, seen locally in
is_instance_of, StructuralEqual::Equal and StructuralHash::Hash).

Changes

  • register_types() registers the four types of the file (PointObj,
    Point3Obj, CounterObj, LeafObj) once, behind a std::sync::Once, and
    each test calls it first. All registrations then finish before any test
    reads the table. The tests still run in parallel.

Not changed

  • The runtime and the derive. A program that registers a type on first use
    while another thread uses tvm-ffi can still hit this race. This PR only
    removes it from the tests.
  • test_object_registration.rs and test_match_any_ast_lookup.rs also
    register types on first use. Neither failed in 1000 local runs, so they are
    unchanged.

Tests

Local runs of the test_object_reflection binary on Linux:

runs that failed
before, parallel (default) 16 / 500
before, --test-threads=1 0 / 500
after, parallel (default) 0 / 2000

pre-commit is clean.

… them

The types in test_object_reflection.rs register on first use, while tests on
other threads read the type table. The runtime grows the table without a lock,
so a reader can see a moved-out or freed entry: Windows CI failed with "Cannot
find type info for type_index=139", and 16 of 500 local runs crashed.

Each test now first registers every type of the file, once, behind a `Once`.
No run failed out of 2000.
@tqchen
tqchen merged commit 963cbb0 into apache:main Oct 22, 2026
8 of 9 checks passed
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