Skip to content

is_collection_enabled is not thread-safe #1398

@qinsoon

Description

@qinsoon

#1075 removed disable/enable_collection and replaced it with Collection::is_collection_enabled. However, it seems a binding cannot implement enable/disable collection in a thread-safe way with the latter API.

Consider a scenario like this:

  1. GC is enabled by default.
  2. Thread 1 tries to allocate and polls for GC. The poll is allowed, thus MMTk schedules work packets for the GC. However, none of the work packets has been executed yet (including StopMutators and Collection::stop_all_mutators).
  3. Thread 2 tries to disable GC. It sets a binding-side flag, and future Collection::is_collection_enabled will return this flag value. Thread 2 further invokes a GC safe point to make sure there is no ongoing GC request yet. As stop_all_mutators has not been called yet, the binding does not know there is a GC and the safe point simply returns.
  4. Thread 2 starts to execute code that is supposed to run only when GC is disabled.
  5. StopMutators gets executed by MMTk, and it asks the binding to stop mutators.
  6. Thread 2 runs to a GC safe point, and gets stopped at a place where GC is not supposed to happen.

Though the document for is_collection_enabled states that 'any synchronization involving enabling and disabling collections by mutator threads should be implemented by the VM', there seems to be no way for the VM to do this.

The core issue is that there exists a window between when MMTk polls for GC and when it executes stop_all_mutators.
During this window:

  • MMTk already considers a GC in progress.
  • The binding, however, cannot detect that GC has been triggered.

If the binding disables GC in that interval, the two states diverge -- leading to GC happening when the VM assumes it cannot.

The previous enable/disable_collection API did not have this problem. When the binding called these methods, MMTk could internally check whether a GC was ongoing and block the call until the GC completed, ensuring proper synchronization.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions