Skip to content

Segfault with no-naked-pointers and recursive modules #10203

@stedolan

Description

@stedolan

Trunk can currently segfault during GC, due to a bad interaction between the new closure representation (relied upon in no-naked-pointers mode) and the way that recursive modules are initialised.

During recursive module initialisation, a stub closure is directly overwritten with the contents of another closure, once the recursive closure has been built. The current code in camlInternalMod is careful to ensure that both the old and new closures are valid and the correct intrinsics in Obj are used to mutate them.

However, this isn't enough, as incremental garbage collection can still get mixed up between the old and new layouts. The sequence of events that goes wrong is:

  • Stub closure created with env_offset = 2, length = 11
  • GC begins, pushes an entry to the mark stack representing the interval [2, 11] of the stub closure's fields
  • Recursive module initialisation constructs final closure (with env_offset = 3) and overwrites stub
  • GC continues, popping closure fields [2, 11] from mark stack and starts marking

We end up marking field 2 of a closure which by that point has env_offset = 3. Field 2 of this closure is not a markable value (it's a code pointer), so this segfaults.

(This came up during an attempt to benchmark #10195 using sandmark: cubicle segfaults on startup due to this bug)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions