-
-
Notifications
You must be signed in to change notification settings - Fork 82
Cyclic type reference causes hang #423
Description
A runtime bug was introduced when loading an assembly that contains a cyclic datastructure. The following code is valid Mun code because Foo is garbage collected type (even though its impossible to create this type at runtime).
pub struct Foo {
foo: Foo
}When loading a munlib at runtime that contains this type the runtime hangs. This is due to the code in assembly.rs:
mun/crates/mun_runtime/src/assembly.rs
Lines 215 to 223 in fa07c5c
| // Load all types | |
| while let Some(type_info) = types_to_load.pop_front() { | |
| match TypeInfo::try_from_abi(type_info, &type_table) { | |
| Ok(type_info) => { | |
| assert!(type_table.insert_type(Arc::new(type_info)).is_none()) | |
| } | |
| Err(TryFromAbiError::UnknownTypeId(_)) => types_to_load.push_back(type_info), | |
| } | |
| } |
When loading the type Foo, if the type Foo is not yet in the TypeTable loading the above snippet will fail.
We could do something by first creating the Arc<TypeInfo> and then injecting it somehow but it raises another interesting question. By storing the Arc<TypeInfo> in the field, we create a cycle. However, storing the type of a field as a Weak<TypeInfo> is also not an option in a case like this:
pub struct Foo {
bar: Bar
}
pub struct Bar {
foo: Foo
}If in the case above we only hold an Arc<TypeInfo> of Bar, the type info of Foo might be dropped which is not what we want.
I see two approaches in solving this:
- Always retain all the TypeInfos ever allocated. Memory will grow over time, but I doubt it will become a major issue.
- Garbage collect TypeInfos.
The first option is definitely the easiest to implement, I recommend we first take that approach and optimize later. WDYT?