diff --git a/CHANGELOG.md b/CHANGELOG.md index ddea6c5ac..d99423243 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - ESP32: fix i2c_driver_acquire and i2c_driver_release functions, that were working only once. +- Sending messages to registered processes using the `!` operator now works. ## [0.6.0-beta.0] - 2024-02-08 diff --git a/src/libAtomVM/opcodesswitch.h b/src/libAtomVM/opcodesswitch.h index b27df2be3..613c0d6a3 100644 --- a/src/libAtomVM/opcodesswitch.h +++ b/src/libAtomVM/opcodesswitch.h @@ -2213,7 +2213,18 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb) #endif #ifdef IMPL_EXECUTE_LOOP - int local_process_id = term_to_local_process_id(x_regs[0]); + term recipient_term = x_regs[0]; + int local_process_id; + if (term_is_pid(recipient_term)) { + local_process_id = term_to_local_process_id(recipient_term); + } else if (term_is_atom(recipient_term)) { + local_process_id = globalcontext_get_registered_process(ctx->global, term_to_atom_index(recipient_term)); + if (UNLIKELY(local_process_id == 0 )) { + RAISE_ERROR(BADARG_ATOM); + } + } else { + RAISE_ERROR(BADARG_ATOM); + } TRACE("send/0 target_pid=%i\n", local_process_id); TRACE_SEND(ctx, x_regs[0], x_regs[1]); globalcontext_send_message(ctx->global, local_process_id, x_regs[1]); diff --git a/tests/erlang_tests/send_receive.erl b/tests/erlang_tests/send_receive.erl index 7c673f260..54b9c4ec4 100644 --- a/tests/erlang_tests/send_receive.erl +++ b/tests/erlang_tests/send_receive.erl @@ -23,10 +23,44 @@ -export([start/0, send_test/2]). start() -> + Test0 = test_send2(), + Test1 = test_send(), + Test2 = test_send_to_int(), + Test3 = test_send_to_atom(), + Test0 + Test1 + Test2 + Test3. + +send_test(V, P) -> + P ! V. + +%priv + +%% test send to pid +test_send2() -> send_test(9, self()), receive - Value -> Value * 2 + Value -> Value end. -send_test(V, P) -> - P ! V. +%% test send to registered process +test_send() -> + erlang:register(tester, self()), + send_test(6, tester), + receive + RegisteredVal -> RegisteredVal + end. + +%% test send to integer +test_send_to_int() -> + try 1 ! 1 of + _Any -> 0 + catch + error:badarg -> 2 + end. + +%% test send to non-registered atom +test_send_to_atom() -> + try test ! nobody of + _Any -> 0 + catch + error:badarg -> 1 + end.