Skip to content

Fix race condition right after ubf registration#16307

Merged
luke-gru merged 1 commit intoruby:masterfrom
luke-gruber:thread_join_finalizers
Mar 9, 2026
Merged

Fix race condition right after ubf registration#16307
luke-gru merged 1 commit intoruby:masterfrom
luke-gruber:thread_join_finalizers

Conversation

@luke-gruber
Copy link
Copy Markdown
Contributor

@luke-gruber luke-gruber commented Mar 4, 2026

Registering a ubf was considered problematic in some cases because it could
result in lock ordering inversions with the ubf function itself. I believe
this is the reason that in patch be1bbd5, the ubf was registered outside of
the thread_sched_lock.

For example, thread_sched_to_waiting_until_wakeup() (native_sleep)
should register the ubf with the thread_sched_lock (TSL) taken. The ordering
is (TSL -> UBF lock). During the ubf call itself, since the UBF lock is
always acquired during the call, the ordering is (UBF lock -> TSL). This
inversion was avoided by registering the ubf outside the TSL.

This inversion is benign in this case, though. Since there can be no ubf on the
thread before the call to ubf_set, and this ubf is the only place where the
(UBF lock -> TSL lock) ordering is done, it is okay to register it with the TSL.
In fact registering the ubf outside the TSL can result in problamatic race conditions,
so we now register the ubf with the TSL lock.

This fixes a race condition whereby a newly registered ubf is called before the thing it's
protecting (the sleep) is actually run. The sleeping thread can never be interrupted if this
happens.

Fixes [Bug #21926]

@luke-gruber luke-gruber force-pushed the thread_join_finalizers branch 3 times, most recently from 4435d8c to eb8fc15 Compare March 6, 2026 14:20
@luke-gruber luke-gruber changed the title Fix ubfs so that we can register them to be called without ubf lock Fix race condition right after ubf registration. Mar 6, 2026
@luke-gru luke-gru changed the title Fix race condition right after ubf registration. Fix race condition right after ubf registration Mar 6, 2026
Registering a ubf was considered problematic in some cases because it could
result in lock ordering inversions with the ubf function itself. I believe
this is the reason that in patch be1bbd5, the ubf was registered outside of
the `thread_sched_lock`.

For example, `thread_sched_to_waiting_until_wakeup()` (native_sleep)
should register the ubf with the thread_sched_lock (TSL) taken. The ordering
is (TSL -> UBF lock). During the ubf call itself, since the UBF lock is
always acquired during the call, the ordering is (UBF lock -> TSL). This
inversion was avoided by registering the ubf outside the TSL.

This inversion is benign in this case, though. Since there can be no ubf on the
thread before the call to `ubf_set`, and this ubf is the only place where the
(UBF lock -> TSL lock) ordering is done, it is okay to register it with the TSL.
In fact registering the ubf outside the TSL can result in problamatic race conditions,
so we now register the ubf with the TSL lock.

This fixes a race condition whereby a newly registered ubf is called before the thing it's
protecting (the sleep) is actually run. The sleeping thread can never be interrupted if this
happens.

Fixes [Bug #21926]
@luke-gruber luke-gruber force-pushed the thread_join_finalizers branch from eb8fc15 to dc99d65 Compare March 9, 2026 15:42
@luke-gru luke-gru merged commit 0837263 into ruby:master Mar 9, 2026
122 of 129 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants