SanderMertens / flecs

A fast entity component system (ECS) for C & C++
https://www.flecs.dev
Other
6.31k stars 441 forks source link

Infinite recursion when adding component with cyclic `With` relationship #1063

Open kroltan opened 11 months ago

kroltan commented 11 months ago

Describe the bug If two components A and B exist, that have a pair (With, $other), then adding the component to an entity enters into a seemingly infinite recursion and segfaults.

#0  0x0000555555647043 in ecs_vec_count (v=<error reading variable: Cannot access memory at address 0x7fffff7feff8>) at /home/kroltan/Projects/chillworld/flecs/src/datastructures/vec.c:263
#1  0x0000555555687f53 in flecs_entity_index_try_get_any (index=0x5555558ef028, entity=20) at /home/kroltan/Projects/chillworld/flecs/src/storage/entity_index.c:83
#2  0x0000555555687feb in flecs_entity_index_try_get (index=0x5555558ef028, entity=20) at /home/kroltan/Projects/chillworld/flecs/src/storage/entity_index.c:105
#3  0x0000555555688757 in flecs_entity_index_is_alive (index=0x5555558ef028, entity=20) at /home/kroltan/Projects/chillworld/flecs/src/storage/entity_index.c:216
#4  0x0000555555657785 in ecs_get_alive (world=0x5555558eedb0, entity=20) at /home/kroltan/Projects/chillworld/flecs/src/entity.c:3923
#5  0x00005555556997af in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=20, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:812
#6  0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=21, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#7  0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=20, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#8  0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=21, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#9  0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=20, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
(More stack frames follow...)
#65453 0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=20, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#65454 0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=21, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#65455 0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=20, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#65456 0x000055555569995b in flecs_add_with_property (world=0x5555558eedb0, idr_with_wildcard=0x55555595dda0, dst_type=0x7fffffffc730, r=21, o=0) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:837
#65457 0x0000555555699d20 in flecs_find_table_with (world=0x5555558eedb0, node=0x7ffff756b8d0, with=21) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:906
#65458 0x000055555569a363 in flecs_create_edge_for_add (world=0x5555558eedb0, node=0x7ffff756b8d0, edge=0x5555565028a0, id=21) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:1033
#65459 0x000055555569ab7d in flecs_table_traverse_add (world=0x5555558eedb0, node=0x7ffff756b8d0, id_ptr=0x7fffffffc808, diff=0x7fffffffc840) at /home/kroltan/Projects/chillworld/flecs/src/storage/table_graph.c:1097
#65460 0x000055555564aa97 in flecs_add_id (world=0x5555558eedb0, entity=765, id=21) at /home/kroltan/Projects/chillworld/flecs/src/entity.c:955
#65461 0x0000555555650f6b in ecs_add_id (world=0x5555558eedb0, entity=765, id=21) at /home/kroltan/Projects/chillworld/flecs/src/entity.c:2630
#65462 0x0000555555620052 in plecs_create_term (world=0x5555558eedb0, term=0x7fffffffc970, name=0x5555557cc415 "assets/init.plecs", expr=0x55555643ce03 "transform.Position { { 300, 300 } }\n}\nc1 : Cross", column=19, state=0x7fffffffcb70) at /home/kroltan/Projects/chillworld/flecs/src/addons/plecs.c:773
#65463 0x0000555555622e19 in plecs_parse_plecs_term (world=0x5555558eedb0, name=0x5555557cc415 "assets/init.plecs", expr=0x55555643ce03 "transform.Position { { 300, 300 } }\n}\nc1 : Cross", ptr=0x55555643ce16 "{ { 300, 300 } }\n}\nc1 : Cross", state=0x7fffffffcb70) at /home/kroltan/Projects/chillworld/flecs/src/addons/plecs.c:1728
#65464 0x000055555562343a in plecs_parse_stmt (world=0x5555558eedb0, name=0x5555557cc415 "assets/init.plecs", expr=0x55555643ce01 "- transform.Position { { 300, 300 } }\n}\nc1 : Cross", ptr=0x55555643ce03 "transform.Position { { 300, 300 } }\n}\nc1 : Cross", state=0x7fffffffcb70) at /home/kroltan/Projects/chillworld/flecs/src/addons/plecs.c:1871
#65465 0x0000555555623c41 in flecs_plecs_parse (world=0x5555558eedb0, name=0x5555557cc415 "assets/init.plecs", expr=0x55555643ce01 "- transform.Position { { 300, 300 } }\n}\nc1 : Cross", vars=0x0, script=0, instance=0) at /home/kroltan/Projects/chillworld/flecs/src/addons/plecs.c:2057
#65466 0x0000555555623e21 in ecs_plecs_from_str (world=0x5555558eedb0, name=0x5555557cc415 "assets/init.plecs", expr=0x55555643c6b0 "Prefab Black {\n    - sdf.Order { 1 }\n\n    _ :- sdf.Order { 1 }, sdf.Onion\n    _ :- sdf.Order { 2 }, sdf.Offset { -3 }\n    _ :- sdf.Order { 3 }, sdf.Solid { color: {0, 0, 0, 255} }\n}\n\nPrefab Red {\n    - sdf.Order { 2 }\n    _ :- sdf.Order { 1 }, sdf.Solid { "...) at /home/kroltan/Projects/chillworld/flecs/src/addons/plecs.c:2106
#65467 0x000055555562401e in ecs_plecs_from_file (world=0x5555558eedb0, filename=0x5555557cc415 "assets/init.plecs") at /home/kroltan/Projects/chillworld/flecs/src/addons/plecs.c:2162
#65468 0x000055555556779a in flecs::world::plecs_from_file (this=0x7fffffffe040, filename=0x5555557cc415 "assets/init.plecs") at /home/kroltan/Projects/chillworld/flecs/include/flecs/private/../addons/cpp/mixins/plecs/mixin.inl:25
#65469 0x0000555555564e31 in main (argc=1, argv=0x7fffffffe1b8) at /home/kroltan/Projects/chillworld/main.cpp:25
#65470 0x00007ffff7845cd0 in ?? () from /usr/lib/libc.so.6
#65471 0x00007ffff7845d8a in __libc_start_main () from /usr/lib/libc.so.6
#65472 0x0000555555564be5 in _start ()

To Reproduce

struct A { int x; };
struct B { int x; };

world.component<A>().add_second<B>(flecs::With);
world.component<B>().add_second<A>(flecs::With);

world.entity().set(A { .x = 1 });

Expected behavior Adding either component adds the other.

Additional context Using flecs commit 5030db9356927cd5718c128d8911635c44fec537

SanderMertens commented 10 months ago

This is currently not supported as With is an acyclic relationship- for this exact reason, so that the code doesn't have to worry about cycle detection, which comes at a cost. It would be nice to have though, I'll keep this issue open as an enhancement.