Skip to content

Commit 30ac882

Browse files
committed
Panic with unowned subjects
1 parent ab91721 commit 30ac882

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## v1.0.0-rc2 - Unreleased
4+
5+
- `process.receive` will now panic if given a non-named subject that is not
6+
owned by the current process.
7+
38
## v1.0.0-rc1 - 2025-04-24
49

510
- In the `gleam/erlang/process` module:

src/gleam/erlang/process.gleam

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,30 @@ pub fn send(subject: Subject(message), message: message) -> Nil {
219219
///
220220
/// The `within` parameter specifies the timeout duration in milliseconds.
221221
///
222-
@external(erlang, "gleam_erlang_ffi", "receive")
222+
/// ## Panics
223+
///
224+
/// This function will panic if a process tries to receive with a non-named
225+
/// subject that it does not own.
226+
///
223227
pub fn receive(
224228
from subject: Subject(message),
225229
within timeout: Int,
230+
) -> Result(message, Nil) {
231+
case subject {
232+
NamedSubject(..) -> perform_receive(subject, timeout)
233+
Subject(owner:, ..) ->
234+
case owner == self() {
235+
True -> perform_receive(subject, timeout)
236+
False ->
237+
panic as "Cannot receive with a subject owned by another process"
238+
}
239+
}
240+
}
241+
242+
@external(erlang, "gleam_erlang_ffi", "receive")
243+
fn perform_receive(
244+
subject: Subject(message),
245+
timeout: Int,
226246
) -> Result(message, Nil)
227247

228248
/// Receive a message that has been sent to current process using the `Subject`.

test/gleam/erlang/process_test.gleam

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ pub fn receive_test() {
7676
let assert Error(Nil) = process.receive(subject, 0)
7777
}
7878

79+
@external(erlang, "gleam_erlang_test_ffi", "assert_gleam_panic")
80+
fn assert_panic(f: fn() -> t) -> String
81+
82+
pub fn receive_other_test() {
83+
let subject = process.new_subject()
84+
process.spawn(fn() { process.send(subject, process.new_subject()) })
85+
let assert Ok(subject) = process.receive(subject, 20)
86+
87+
assert_panic(fn() { process.receive(subject, 0) })
88+
|> should.equal("Cannot receive with a subject owned by another process")
89+
}
90+
7991
pub fn receive_forever_test() {
8092
let subject = process.new_subject()
8193

test/gleam_erlang_test_ffi.erl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-module(gleam_erlang_test_ffi).
2+
-export([assert_gleam_panic/1]).
3+
4+
assert_gleam_panic(F) ->
5+
try
6+
F(),
7+
erlang:error(expected_panic)
8+
catch
9+
error:#{gleam_error := _, message := M} -> M
10+
end.

0 commit comments

Comments
 (0)