Skip to content

Commit

Permalink
Allow sending message to registered process name
Browse files Browse the repository at this point in the history
Changes `erlang:send/2` to accept a pid or registered process name. Updates
`tests/erlang_tests/test_send_nif_and_echo.erl` to also test sending directly to the registered
name, and `tests/erlang_tests/test_send.erl` to test sending to an an unregistered `atom` name.

Fixes issue atomvm#98

Signed-off-by: Winford <winford@object.stream>
  • Loading branch information
UncleGrumpy committed Jun 12, 2023
1 parent 29825e4 commit c4cf48c
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a bug in when putting integers in bit syntax with integer field sizes
- Fixed numerous bugs in memory allocations that could crash the VM
- Fixed SNTP support that had been broken in IDF 4.x builds
- Fixed `erlang:send/2` not sending to registered name

### Breaking Changes

Expand Down
12 changes: 6 additions & 6 deletions src/libAtomVM/globalcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@
#define SMP_RWLOCK_UNLOCK(lock)
#endif

struct RegisteredProcess
{
struct ListHead registered_processes_list_head;
// struct RegisteredProcess
// {
// struct ListHead registered_processes_list_head;

int atom_index;
int local_process_id;
};
// int atom_index;
// int local_process_id;
// };

GlobalContext *globalcontext_new()
{
Expand Down
8 changes: 8 additions & 0 deletions src/libAtomVM/globalcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ struct GlobalContext
void *platform_data;
};

struct RegisteredProcess
{
struct ListHead registered_processes_list_head;

int atom_index;
int local_process_id;
};

/**
* @brief Creates a new GlobalContext
*
Expand Down
48 changes: 44 additions & 4 deletions src/libAtomVM/nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1284,12 +1284,52 @@ static term nif_erlang_spawn(Context *ctx, int argc, term argv[])
static term nif_erlang_send_2(Context *ctx, int argc, term argv[])
{
UNUSED(argc);
term dest = argv[0];
GlobalContext *glb = ctx->global;
struct ListHead *processes_table_list = synclist_rdlock(&glb->processes_table);

term pid_term = argv[0];
VALIDATE_VALUE(pid_term, term_is_pid);
Context *p = NULL;
struct ListHead *item;
if (term_is_pid(dest) == 1) {
int dest_pid = term_to_local_process_id(dest);
// LIST_FOR_EACH (item, processes_table_list) {
// p = GET_LIST_ENTRY(item, Context, processes_table_head);
// if (p->process_id == test_pid) {
// dest_pid = test_pid;
// }
// }
globalcontext_send_message_nolock(glb, dest_pid, argv[1]);
synclist_unlock(&glb->processes_table);

} else if (term_is_atom(dest) == 1) {
// struct ListHead *processes_table_list = synclist_rdlock(&glb->processes_table);
int atom_index = term_to_atom_index(dest);

int dest_pid = -1;
int test_pid = globalcontext_get_registered_process(glb, atom_index);
if (UNLIKELY(test_pid == 0)) {
synclist_unlock(&glb->processes_table);
RAISE_ERROR(BADARG_ATOM);
}

int local_process_id = term_to_local_process_id(pid_term);
globalcontext_send_message(ctx->global, local_process_id, argv[1]);
LIST_FOR_EACH (item, processes_table_list) {
p = GET_LIST_ENTRY(item, Context, processes_table_head);
if (p->process_id == test_pid) {
dest_pid = test_pid;
}
}
if (UNLIKELY(dest_pid == -1)) {
synclist_unlock(&glb->processes_table);
RAISE_ERROR(BADARG_ATOM);
} else {
globalcontext_send_message_nolock(glb, dest_pid, argv[1]);
synclist_unlock(&glb->processes_table);

}
} else {
synclist_unlock(&glb->processes_table);
RAISE_ERROR(BADARG_ATOM);
}

return argv[1];
}
Expand Down
59 changes: 54 additions & 5 deletions tests/erlang_tests/test_send.erl
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,64 @@

-module(test_send).

-export([start/0, send2/2]).
-export([start/0]).

start() ->
send2(5, 1) + send2(self(), -1).
Dead = spawn(fun() -> ok end),
Sent = send(self(), 32),
receive
Any ->
Recv = Any
end,
Sent - Recv + send_mal(5, 3) + send_bad_atom(bogus, 4) + send_dead(Dead, 6) +
send_registered(8).

send2(A, B) ->
send(A, B) ->
try erlang:send(A, B) of
B -> -1;
Any -> Any
B -> B;
_Any -> -1
catch
error:badarg -> B - 2;
_:_ -> -4
end.

send_mal(A, B) ->
try erlang:send(A, B) of
B -> B;
_Any -> -1
catch
error:badarg -> B - 3;
_:_ -> -4
end.

send_bad_atom(A, B) ->
try erlang:send(A, B) of
B -> B;
_Any -> -1
catch
error:badarg -> B - 4;
_:_ -> -4
end.

send_dead(A, B) ->
try erlang:send(A, B) of
B -> B - 6;
_Any -> -1
catch
error:badarg -> -2;
_:_ -> -4
end.

send_registered(B) ->
erlang:register(listen, self()),
try erlang:send(listen, B) of
B ->
receive
B -> B - 8;
_Any -> -1
end;
_Any ->
-1
catch
error:badarg -> -2;
_:_ -> -4
Expand Down
11 changes: 9 additions & 2 deletions tests/erlang_tests/test_send_nif_and_echo.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,20 @@

start() ->
register(echo, do_open_port(<<"echo">>, [])),
byte_size(echo(<<"Hello World">>)).
byte_size(echo(<<"Hello World">>)) + byte_size(to_pid(erlang:whereis(echo), <<"Hello World">>)).

do_open_port(PortName, Param) ->
open_port({spawn, PortName}, Param).

echo(SendValue) ->
erlang:send(whereis(echo), {self(), SendValue}),
erlang:send(echo, {self(), SendValue}),
receive
Value ->
Value
end.

to_pid(Pid, SendValue) ->
erlang:send(Pid, {self(), SendValue}),
receive
Value ->
Value
Expand Down
4 changes: 2 additions & 2 deletions tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ struct Test tests[] = {
TEST_CASE_EXPECTED(long_atoms, 4),
TEST_CASE_EXPECTED(test_concat_badarg, 4),
TEST_CASE_EXPECTED(register_and_whereis_badarg, 333),
TEST_CASE_EXPECTED(test_send, -3),
TEST_CASE(test_send),
TEST_CASE_EXPECTED(test_open_port_badargs, -21),
TEST_CASE_EXPECTED(prime_ext, 1999),
TEST_CASE_EXPECTED(test_try_case_end, 256),
Expand Down Expand Up @@ -477,7 +477,7 @@ struct Test tests[] = {
TEST_CASE_ATOMVM_ONLY(test_close_console_driver, 0),
TEST_CASE_ATOMVM_ONLY(test_close_echo_driver, 0),
TEST_CASE_ATOMVM_ONLY(test_regecho_driver, 11),
TEST_CASE_ATOMVM_ONLY(test_send_nif_and_echo, 11),
TEST_CASE_ATOMVM_ONLY(test_send_nif_and_echo, 22),

TEST_CASE_EXPECTED(test_code_load_binary, 24),
TEST_CASE_EXPECTED(test_code_load_abs, 24),
Expand Down

0 comments on commit c4cf48c

Please sign in to comment.