Repository navigation
fix(runtime): raise timeout_value only when a receive would wait - #15
Merged
Merged
Conversation
A receive whose after value is not a valid timeout now receives a matching message already in the mailbox, as on BEAM. The receive records the invalid value when it starts and raises timeout_value from its timeout check, which runs once the mailbox scan finds no match. Queued messages that do not match stay in the mailbox, and the receive never waits for a later message. The receive_timeout_domain fixture asserts this order and runs natively and on BEAM.
Inside try, an operation that raised earlier in the body, or in the after expression itself, reaches the handler before the receive scans the mailbox. Without this check a matching message was received while the error was still pending; with an empty mailbox the receive replaced the error with timeout_value. The receive_timeout_domain fixture covers both orders.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A receive whose after value is not a valid timeout raised timeout_value before it looked at the mailbox, so a matching message already queued was never received. BEAM receives that message and raises only when the receive would have to wait.
What changed
Before and after
Before: `self() ! x, receive X -> {got, X} after id(foo) -> tmo end` raised timeout_value natively while BEAM OTP 29 returned {got, x}, and the old fixture failed on BEAM at its first queued-message check.
After: The same receive returns {got, x} natively, all 11 probe cases print what BEAM OTP 29 prints, and the fixture passes 10 of 10 runs natively, with one scheduler and on BEAM.
Nothing on screen changes: this is how compiled Erlang programs behave at run time, shown by their printed results.
Checked
How it was checked
cargo build --release --locked (runtime first, then the compiler)
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked --no-fail-fast
python3 scripts/test-allocator-config.py
nera test (the full end-to-end suite)
nera test receive_timeout_domain, ten times, also with NERA_SCHEDULERS=1, and the same fixture on BEAM OTP 29 ten times
python3 scripts/test-native-timer.py, on this change and on a build of main
Probe programs compiled natively before and after the change and run on BEAM OTP 29
Risk
Risk above low: Blast radius, medium — Every receive with an after clause compiles through the changed lowering and check
Full risk assessment
Not done
A receive with an invalid after value, inside a try ... after cleanup block that runs in another try, now raises the earlier error instead of timeout_value; the cause is the separate defect that runs such cleanup blocks with the error still pending.
Windows was not run, and Linux ran only in CI.