Skip to content

Commit

Permalink
Fix actor init timeout sending exit message to linked parent
Browse files Browse the repository at this point in the history
  • Loading branch information
sbergen authored and lpil committed Dec 10, 2024
1 parent d72aeb3 commit 4e338a3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/gleam/otp/actor.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ pub fn start_spec(spec: Spec(state, msg)) -> Result(Subject(msg), StartError) {

// Child did not finish initialising in time
Error(Nil) -> {
// Unlink the child before killing it, so that we only return the error,
// but don't also send an exit message to the linked parent process.
process.unlink(child)
process.kill(child)
Error(InitTimeout)
}
Expand Down
26 changes: 26 additions & 0 deletions test/gleam/otp/actor_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,32 @@ pub fn failed_init_test() {
|> should.be_true
}

pub fn timed_out_init_test() {
process.trap_exits(True)
let exit_selector =
process.new_selector()
|> process.selecting_trapped_exits(function.identity)

let result =
actor.Spec(
init: fn() {
process.sleep(1000)
panic as "should not be reached"
},
loop: fn(_msg, _state) { panic as "should not be reached" },
init_timeout: 1,
)
|> actor.start_spec

// Check that the exit isn't unhandled: it should be handled by start_spec.
// Stop trapping exits before asserting, to avoid interfering with other tests.
let exit = process.select(exit_selector, 10)
process.trap_exits(False)

result |> should.equal(Error(actor.InitTimeout))
exit |> should.equal(Error(Nil))
}

pub fn suspend_resume_test() {
let assert Ok(subject) =
actor.start(0, fn(_msg, iter) { actor.continue(iter + 1) })
Expand Down

0 comments on commit 4e338a3

Please sign in to comment.