diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b68ef9..d656b5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased + +- Fixed a bug where using `actor.Stop(process.Abnormal(...))` would stop + the process with `Normal`. + ## v0.16.1 - 2025-01-20 - Fixed a bug where the static supervisor would return the incorrect value if diff --git a/src/gleam/otp/actor.gleam b/src/gleam/otp/actor.gleam index 72f6e9e..fbe6380 100644 --- a/src/gleam/otp/actor.gleam +++ b/src/gleam/otp/actor.gleam @@ -257,6 +257,11 @@ pub type Spec(state, msg) { // TODO: Check needed functionality here to be OTP compatible fn exit_process(reason: ExitReason) -> ExitReason { + case reason { + Abnormal(reason) -> process.send_abnormal_exit(process.self(), reason) + _ -> Nil + } + // TODO reason } @@ -407,7 +412,7 @@ fn initialise_actor( // The init failed. Exit with an error. Failed(reason) -> { process.send(ack, Error(Abnormal(reason))) - exit_process(Abnormal(reason)) + exit_process(process.Normal) } } } diff --git a/test/gleam/otp/actor_test.gleam b/test/gleam/otp/actor_test.gleam index b93ec89..e42211e 100644 --- a/test/gleam/otp/actor_test.gleam +++ b/test/gleam/otp/actor_test.gleam @@ -231,6 +231,31 @@ pub fn replace_selector_test() { |> should.equal(dynamic.from("unknown message: String")) } +pub fn abnormal_exit_can_be_trapped_test() { + process.trap_exits(True) + let exits = + process.new_selector() + |> process.selecting_trapped_exits(function.identity) + + // Make an actor exit with an abnormal reason + let assert Ok(subject) = + actor.start(Nil, fn(_, _) { actor.Stop(process.Abnormal("reason")) }) + process.send(subject, Nil) + + let trapped_reason = process.select(exits, 10) + + // Stop trapping exits, as otherwise other tests fail + process.trap_exits(False) + + trapped_reason + |> should.equal( + Ok(process.ExitMessage( + process.subject_owner(subject), + process.Abnormal("reason"), + )), + ) +} + fn mapped_selector(mapper: fn(a) -> ActorMessage) { let subject = process.new_subject()