Project

General

Profile

Actions

Feature #22139

closed

Prohibit `END{}`/`Kernel#at_exit` in non-main Ractor

Feature #22139: Prohibit `END{}`/`Kernel#at_exit` in non-main Ractor

Added by ko1 (Koichi Sasada) 25 days ago. Updated 16 days ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:125903]

Description

Let's prohibit END{}/Kernel#at_exit on non-main Ractor.

The current behavior is strange:

Ractor.new{
  at_exit{ p [self, Ractor.current] }
}

sleep 1
#=> [#<Ractor:#2 t.rb:2 terminated>, #<Ractor:#1 running>]

There are some options:

  1. prohibit them. Simple.
  2. invoke the block at the end of the Ractor.
  3. invoke the block at the end of the process on main Ractor. It is similar idea of the current behavior.

2 is rejected clearly by Matz because of the semantic gap with current behavior.
3 is no problem because the block and reachable objects from the block can be inherited to main Ractor.
However, to make it simple, now let's prohibit them (1), and revisit if we found the (3) is needed.

Updated by ko1 (Koichi Sasada) 17 days ago Actions #2 [ruby-core:125995]

This change was approved by Matz.

Updated by ko1 (Koichi Sasada) 17 days ago Actions #3

  • Status changed from Open to Closed

Applied in changeset git|7896d376fb9cb602e2f5b26436c2ed8412b1ab9b.


Prohibit at_exit and END{} in non-main Ractors

Registering an exit handler with Kernel#at_exit or END{} in a non-main
Ractor behaved confusingly: the block ran in the main Ractor at process
exit even though it was registered from another Ractor. Raise
Ractor::IsolationError instead.

[Feature #22139]

Co-Authored-By: Claude Opus 4.8 (1M context)

Updated by matz (Yukihiro Matsumoto) 16 days ago Actions #4 [ruby-core:126021]

I agree with prohibiting END{} and at_exit in non-main Ractors (option 1).

The current behavior is accidental rather than designed, and as I said before, invoking the block at the end of the Ractor (option 2) changes the meaning of at_exit too much. Option 3 is semantically consistent, but I doubt anyone actually wants blocks registered in a Ractor to fire on the main Ractor at process exit; the sharing/inheritance of reachable objects is also subtle. Starting with the simple prohibition is the right move. If real use cases emerge, we can relax it toward option 3 later, since going from an error to defined behavior is compatible.

Matz.

Actions

Also available in: PDF Atom