From 261a031c6ad95657f5aeaa084ab41e4f62b6bab6 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Sat, 26 Aug 2023 23:09:20 +0200 Subject: [PATCH] Fix and factorize spawn functions Implement `erlang:spawn_link/1,3` Fix options of `spawn_opt/2` by factorizing it with `spawn_opt/4` Also rewrite `spawn/1` and `spawn/3` in Erlang and update tests accordingly Also isolate libs tests Also move types declaration in erlang module to the top Signed-off-by: Paul Guyot --- CHANGELOG.md | 1 + examples/emscripten/CMakeLists.txt | 2 +- libs/estdlib/src/erlang.erl | 59 +++-- libs/etest/src/etest.erl | 27 ++ src/libAtomVM/nifs.c | 238 +++++++++--------- src/libAtomVM/nifs.gperf | 2 - tests/erlang_tests/call_with_ref_test.erl | 2 +- tests/erlang_tests/copy_terms0.erl | 4 +- tests/erlang_tests/copy_terms1.erl | 4 +- tests/erlang_tests/copy_terms10.erl | 3 +- tests/erlang_tests/copy_terms11.erl | 4 +- tests/erlang_tests/copy_terms12.erl | 4 +- tests/erlang_tests/copy_terms13.erl | 4 +- tests/erlang_tests/copy_terms14.erl | 4 +- tests/erlang_tests/copy_terms15.erl | 4 +- tests/erlang_tests/copy_terms16.erl | 4 +- tests/erlang_tests/copy_terms17.erl | 2 +- tests/erlang_tests/copy_terms18.erl | 3 +- tests/erlang_tests/copy_terms2.erl | 4 +- tests/erlang_tests/copy_terms3.erl | 4 +- tests/erlang_tests/copy_terms4.erl | 4 +- tests/erlang_tests/copy_terms5.erl | 4 +- tests/erlang_tests/copy_terms6.erl | 4 +- tests/erlang_tests/copy_terms7.erl | 4 +- tests/erlang_tests/copy_terms8.erl | 4 +- tests/erlang_tests/copy_terms9.erl | 3 +- tests/erlang_tests/gen_server_like_test.erl | 2 +- tests/erlang_tests/guards3.erl | 2 +- tests/erlang_tests/is_type.erl | 7 +- tests/erlang_tests/link_kill_parent.erl | 4 +- tests/erlang_tests/link_throw.erl | 6 +- tests/erlang_tests/pingpong.erl | 4 +- tests/erlang_tests/prime.erl | 6 +- tests/erlang_tests/prime_ext.erl | 6 +- tests/erlang_tests/send_to_dead_process.erl | 4 +- tests/erlang_tests/sleep.erl | 11 +- tests/erlang_tests/spawn_fun1.erl | 2 +- tests/erlang_tests/spawn_fun2.erl | 2 +- tests/erlang_tests/spawn_fun3.erl | 2 +- tests/erlang_tests/spawn_opt_link_normal.erl | 4 +- tests/erlang_tests/state_test.erl | 2 +- tests/erlang_tests/state_test2.erl | 2 +- tests/erlang_tests/state_test3.erl | 2 +- tests/erlang_tests/test_bs.erl | 12 +- tests/erlang_tests/test_is_process_alive.erl | 21 +- tests/erlang_tests/test_min_heap_size.erl | 2 +- tests/erlang_tests/test_monitor.erl | 22 +- tests/erlang_tests/test_pids_ordering.erl | 12 +- tests/erlang_tests/test_raise.erl | 2 +- tests/erlang_tests/test_refc_binaries.erl | 8 +- tests/erlang_tests/test_selective_receive.erl | 57 +++-- tests/erlang_tests/test_send.erl | 7 +- tests/erlang_tests/test_stacktrace.erl | 5 +- tests/erlang_tests/test_sub_binaries.erl | 8 +- tests/erlang_tests/test_system_info.erl | 2 +- .../erlang_tests/test_throw_call_ext_last.erl | 4 +- .../erlang_tests/test_timeout_not_integer.erl | 4 +- tests/erlang_tests/trap_exit_flag.erl | 81 +++--- tests/erlang_tests/unlink_error.erl | 2 +- tests/erlang_tests/whereis_dead_process.erl | 2 +- tests/libs/estdlib/CMakeLists.txt | 1 + tests/libs/estdlib/test_gen_server.erl | 13 +- tests/libs/estdlib/test_gen_statem.erl | 13 +- tests/libs/estdlib/test_spawn.erl | 68 +++++ tests/libs/estdlib/tests.erl | 1 + tests/test.c | 2 +- 66 files changed, 482 insertions(+), 337 deletions(-) create mode 100644 tests/libs/estdlib/test_spawn.erl diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ff2b932c..f8fb3ced0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ functions that default to `?ATOMVM_NVS_NS` are deprecated now). - Added most format possibilities to `io:format/2` and `io_lib:format/2` - Added `unicode` module with `characters_to_list/1,2` and `characters_to_binary/1,2,3` functions - Added support for `crypto:hash/2` (ESP32 and generic_unix with openssl) +- Added erlang:spawn_link/1,3 - Added links to process_info/2 ### Fixed diff --git a/examples/emscripten/CMakeLists.txt b/examples/emscripten/CMakeLists.txt index d8bea697c..6856d88e8 100644 --- a/examples/emscripten/CMakeLists.txt +++ b/examples/emscripten/CMakeLists.txt @@ -22,7 +22,7 @@ project(examples_emscripten) include(BuildErlang) -pack_runnable(run_script run_script eavmlib) +pack_runnable(run_script run_script estdlib eavmlib) pack_runnable(call_cast call_cast eavmlib) pack_runnable(html5_events html5_events estdlib eavmlib) pack_runnable(wasm_webserver wasm_webserver estdlib eavmlib) diff --git a/libs/estdlib/src/erlang.erl b/libs/estdlib/src/erlang.erl index ad6c52328..6f26e90ea 100644 --- a/libs/estdlib/src/erlang.erl +++ b/libs/estdlib/src/erlang.erl @@ -74,6 +74,8 @@ whereis/1, spawn/1, spawn/3, + spawn_link/1, + spawn_link/3, spawn_opt/2, spawn_opt/4, link/1, @@ -119,6 +121,19 @@ MegaSecs :: non_neg_integer(), Secs :: non_neg_integer(), MicroSecs :: non_neg_integer }. +-type float_format_option() :: + {decimals, Decimals :: 0..57} + | {scientific, Decimals :: 0..57} + | compact. + +-type demonitor_option() :: flush | {flush, boolean()} | info | {info, boolean()}. + +-type spawn_option() :: + {min_heap_size, pos_integer()} + | {max_heap_size, pos_integer()} + | link + | monitor. + %%----------------------------------------------------------------------------- %% @param Time time in milliseconds after which to send the timeout message. %% @param Dest Pid or server name to which to send the timeout message. @@ -612,11 +627,6 @@ atom_to_binary(_Atom, _Encoding) -> atom_to_list(_Atom) -> erlang:nif_error(undefined). --type float_format_option() :: - {decimals, Decimals :: 0..57} - | {scientific, Decimals :: 0..57} - | compact. - %%----------------------------------------------------------------------------- %% @param Float Float to convert %% @returns a binary with a text representation of the float @@ -774,8 +784,8 @@ whereis(_Name) -> %% @end %%----------------------------------------------------------------------------- -spec spawn(Function :: function()) -> pid(). -spawn(_Name) -> - erlang:nif_error(undefined). +spawn(Function) -> + erlang:spawn_opt(Function, []). %%----------------------------------------------------------------------------- %% @param Module module of the function to create a process from @@ -786,14 +796,31 @@ spawn(_Name) -> %% @end %%----------------------------------------------------------------------------- -spec spawn(Module :: module(), Function :: atom(), Args :: [any()]) -> pid(). -spawn(_Module, _Function, _Args) -> - erlang:nif_error(undefined). +spawn(Module, Function, Args) -> + erlang:spawn_opt(Module, Function, Args, []). --type spawn_option() :: - {min_heap_size, pos_integer()} - | {max_heap_size, pos_integer()} - | link - | monitor. +%%----------------------------------------------------------------------------- +%% @param Function function to create a process from +%% @returns pid of the new process +%% @doc Create a new process and link it. +%% @end +%%----------------------------------------------------------------------------- +-spec spawn_link(Function :: function()) -> pid(). +spawn_link(Function) -> + erlang:spawn_opt(Function, [link]). + +%%----------------------------------------------------------------------------- +%% @param Module module of the function to create a process from +%% @param Function name of the function to create a process from +%% @param Args arguments to pass to the function to create a process from +%% @returns pid of the new process +%% @doc Create a new process by calling exported Function from Module with Args +%% and link it. +%% @end +%%----------------------------------------------------------------------------- +-spec spawn_link(Module :: module(), Function :: atom(), Args :: [any()]) -> pid(). +spawn_link(Module, Function, Args) -> + erlang:spawn_opt(Module, Function, Args, [link]). %%----------------------------------------------------------------------------- %% @param Function function to create a process from @@ -802,7 +829,7 @@ spawn(_Module, _Function, _Args) -> %% @doc Create a new process. %% @end %%----------------------------------------------------------------------------- --spec spawn_opt(Function :: function(), Options :: [{max_heap_size, integer()}]) -> +-spec spawn_opt(Function :: function(), Options :: [spawn_option()]) -> pid() | {pid(), reference()}. spawn_opt(_Name, _Options) -> erlang:nif_error(undefined). @@ -889,8 +916,6 @@ monitor(_Type, _Pid) -> demonitor(_Monitor) -> erlang:nif_error(undefined). --type demonitor_option() :: flush | {flush, boolean()} | info | {info, boolean()}. - %%----------------------------------------------------------------------------- %% @param Monitor reference of monitor to remove %% @returns `true' diff --git a/libs/etest/src/etest.erl b/libs/etest/src/etest.erl index 9bbc0b303..20aa3bb69 100644 --- a/libs/etest/src/etest.erl +++ b/libs/etest/src/etest.erl @@ -119,8 +119,35 @@ assert_failure(F, E) -> %% @private run_test(Test) -> + Parent = self(), + {Pid, Ref} = spawn_opt( + fun() -> + Result = do_run_test(Test), + Parent ! {self(), Result} + end, + [monitor] + ), + receive + {Pid, Result} -> + receive + {'DOWN', Ref, process, Pid, normal} -> ok + after 0 -> ok + end, + Result; + {'DOWN', Ref, process, Pid, Reason} -> + {error, Reason} + end. + +do_run_test(Test) -> try Result = Test:test(), + Value = process_flag(trap_exit, false), + case Value of + true -> + erlang:display({test, Test, unexpected_trap_exit}); + false -> + ok + end, case erlang:system_info(machine) of "BEAM" -> io:format("+"); diff --git a/src/libAtomVM/nifs.c b/src/libAtomVM/nifs.c index eed0b7f98..17c8ff436 100644 --- a/src/libAtomVM/nifs.c +++ b/src/libAtomVM/nifs.c @@ -121,8 +121,8 @@ static term nif_erlang_register_2(Context *ctx, int argc, term argv[]); static term nif_erlang_unregister_1(Context *ctx, int argc, term argv[]); static term nif_erlang_send_2(Context *ctx, int argc, term argv[]); static term nif_erlang_setelement_3(Context *ctx, int argc, term argv[]); -static term nif_erlang_spawn(Context *ctx, int argc, term argv[]); -static term nif_erlang_spawn_fun(Context *ctx, int argc, term argv[]); +static term nif_erlang_spawn_opt(Context *ctx, int argc, term argv[]); +static term nif_erlang_spawn_fun_opt(Context *ctx, int argc, term argv[]); static term nif_erlang_whereis_1(Context *ctx, int argc, term argv[]); static term nif_erlang_system_time_1(Context *ctx, int argc, term argv[]); static term nif_erlang_tuple_to_list_1(Context *ctx, int argc, term argv[]); @@ -410,28 +410,16 @@ static const struct Nif unregister_nif = .nif_ptr = nif_erlang_unregister_1 }; -static const struct Nif spawn_nif = -{ - .base.type = NIFFunctionType, - .nif_ptr = nif_erlang_spawn -}; - static const struct Nif spawn_opt_nif = { .base.type = NIFFunctionType, - .nif_ptr = nif_erlang_spawn -}; - -static const struct Nif spawn_fun_nif = -{ - .base.type = NIFFunctionType, - .nif_ptr = nif_erlang_spawn_fun + .nif_ptr = nif_erlang_spawn_opt }; static const struct Nif spawn_fun_opt_nif = { .base.type = NIFFunctionType, - .nif_ptr = nif_erlang_spawn_fun + .nif_ptr = nif_erlang_spawn_fun_opt }; static const struct Nif send_nif = @@ -1081,20 +1069,98 @@ static NativeHandlerResult process_console_mailbox(Context *ctx) return result; } -static term nif_erlang_spawn_fun(Context *ctx, int argc, term argv[]) +// Common handling of spawn/1, spawn/3, spawn_opt/2, spawn_opt/4 +// opts_term is [] for spawn/1,3 +static term do_spawn(Context *ctx, Context *new_ctx, term opts_term) { - term fun_term = argv[0]; - term opts_term = argv[1]; - VALIDATE_VALUE(fun_term, term_is_function); + term min_heap_size_term = interop_proplist_get_value(opts_term, MIN_HEAP_SIZE_ATOM); + term max_heap_size_term = interop_proplist_get_value(opts_term, MAX_HEAP_SIZE_ATOM); + term link_term = interop_proplist_get_value(opts_term, LINK_ATOM); + term monitor_term = interop_proplist_get_value(opts_term, MONITOR_ATOM); - if (argc == 2) { - // spawn_opt has been called - VALIDATE_VALUE(opts_term, term_is_list); + if (min_heap_size_term != term_nil()) { + if (UNLIKELY(!term_is_integer(min_heap_size_term))) { + // Context was not scheduled yet, we can destroy it. + context_destroy(new_ctx); + RAISE_ERROR(BADARG_ATOM); + } + new_ctx->has_min_heap_size = 1; + new_ctx->min_heap_size = term_to_int(min_heap_size_term); } else { - // regular spawn - opts_term = term_nil(); + min_heap_size_term = term_from_int(0); + } + if (max_heap_size_term != term_nil()) { + if (UNLIKELY(!term_is_integer(max_heap_size_term))) { + context_destroy(new_ctx); + RAISE_ERROR(BADARG_ATOM); + } + new_ctx->has_max_heap_size = 1; + new_ctx->max_heap_size = term_to_int(max_heap_size_term); + } + + if (new_ctx->has_min_heap_size && new_ctx->has_max_heap_size) { + if (term_to_int(min_heap_size_term) > term_to_int(max_heap_size_term)) { + context_destroy(new_ctx); + RAISE_ERROR(BADARG_ATOM); + } } + uint64_t ref_ticks = 0; + + if (link_term == TRUE_ATOM) { + if (UNLIKELY(context_link(new_ctx, term_from_local_process_id(ctx->process_id)) < 0)) { + context_destroy(new_ctx); + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + // This is a really simple hack to get the parent - child linking + // I don't really like how it is implemented but it works nicely. + // I think it should be implemented adding a parent field to Context. + if (UNLIKELY(context_link(ctx, term_from_local_process_id(new_ctx->process_id)) < 0)) { + context_destroy(new_ctx); + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + } + if (monitor_term == TRUE_ATOM) { + ref_ticks = context_monitor(new_ctx, term_from_local_process_id(ctx->process_id)); + if (UNLIKELY(ref_ticks == 0)) { + context_destroy(new_ctx); + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + } + + term new_pid = term_from_local_process_id(new_ctx->process_id); + + if (ref_ticks) { + int res_size = REF_SIZE + TUPLE_SIZE(2); + if (UNLIKELY(memory_ensure_free_opt(ctx, res_size, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { + context_destroy(new_ctx); + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + + scheduler_init_ready(new_ctx); + + term ref = term_from_ref_ticks(ref_ticks, &ctx->heap); + + term pid_ref_tuple = term_alloc_tuple(2, &ctx->heap); + term_put_tuple_element(pid_ref_tuple, 0, new_pid); + term_put_tuple_element(pid_ref_tuple, 1, ref); + + return pid_ref_tuple; + } else { + scheduler_init_ready(new_ctx); + return new_pid; + } +} + +static term nif_erlang_spawn_fun_opt(Context *ctx, int argc, term argv[]) +{ + UNUSED(argc); + + term fun_term = argv[0]; + term opts_term = argv[1]; + VALIDATE_VALUE(fun_term, term_is_function); + VALIDATE_VALUE(opts_term, term_is_list); + Context *new_ctx = context_new(ctx->global); new_ctx->group_leader = ctx->group_leader; @@ -1134,22 +1200,13 @@ static term nif_erlang_spawn_fun(Context *ctx, int argc, term argv[]) new_ctx->saved_ip = fun_module->labels[label]; new_ctx->cp = module_address(fun_module->module_index, fun_module->end_instruction_ii); - term max_heap_size_term = interop_proplist_get_value(opts_term, MAX_HEAP_SIZE_ATOM); - if (max_heap_size_term != term_nil()) { - new_ctx->has_max_heap_size = 1; - //TODO: check type, make sure max_heap_size_term is an int32 - new_ctx->max_heap_size = term_to_int(max_heap_size_term); - } - - term result = term_from_local_process_id(new_ctx->process_id); - - scheduler_init_ready(new_ctx); - - return result; + return do_spawn(ctx, new_ctx, opts_term); } -static term nif_erlang_spawn(Context *ctx, int argc, term argv[]) +static term nif_erlang_spawn_opt(Context *ctx, int argc, term argv[]) { + UNUSED(argc); + term module_term = argv[0]; term function_term = argv[1]; term args_term = argv[2]; @@ -1157,14 +1214,7 @@ static term nif_erlang_spawn(Context *ctx, int argc, term argv[]) VALIDATE_VALUE(module_term, term_is_atom); VALIDATE_VALUE(function_term, term_is_atom); VALIDATE_VALUE(args_term, term_is_list); - - if (argc == 4) { - // spawn_opt has been called - VALIDATE_VALUE(opts_term, term_is_list); - } else { - // regular spawn - opts_term = term_nil(); - } + VALIDATE_VALUE(opts_term, term_is_list); Context *new_ctx = context_new(ctx->global); new_ctx->group_leader = ctx->group_leader; @@ -1191,99 +1241,37 @@ static term nif_erlang_spawn(Context *ctx, int argc, term argv[]) new_ctx->saved_ip = found_module->labels[label]; new_ctx->cp = module_address(found_module->module_index, found_module->end_instruction_ii); - term min_heap_size_term = interop_proplist_get_value(opts_term, MIN_HEAP_SIZE_ATOM); - term max_heap_size_term = interop_proplist_get_value(opts_term, MAX_HEAP_SIZE_ATOM); - term link_term = interop_proplist_get_value(opts_term, LINK_ATOM); - term monitor_term = interop_proplist_get_value(opts_term, MONITOR_ATOM); + //TODO: check available registers count + int reg_index = 0; + size_t min_heap_size = 0; + term min_heap_size_term = interop_proplist_get_value(opts_term, MIN_HEAP_SIZE_ATOM); if (min_heap_size_term != term_nil()) { if (UNLIKELY(!term_is_integer(min_heap_size_term))) { - //TODO: gracefully handle this error - AVM_ABORT(); - } - new_ctx->has_min_heap_size = 1; - new_ctx->min_heap_size = term_to_int(min_heap_size_term); - } else { - min_heap_size_term = term_from_int(0); - } - if (max_heap_size_term != term_nil()) { - if (UNLIKELY(!term_is_integer(max_heap_size_term))) { - //TODO: gracefully handle this error - AVM_ABORT(); - } - new_ctx->has_max_heap_size = 1; - new_ctx->max_heap_size = term_to_int(max_heap_size_term); - } - - if (new_ctx->has_min_heap_size && new_ctx->has_max_heap_size) { - if (term_to_int(min_heap_size_term) > term_to_int(max_heap_size_term)) { + // Context was not scheduled yet, we can destroy it. + context_destroy(new_ctx); RAISE_ERROR(BADARG_ATOM); } + min_heap_size = term_to_int(min_heap_size_term); } - - uint64_t ref_ticks = 0; - - if (link_term == TRUE_ATOM) { - if (UNLIKELY(context_link(new_ctx, term_from_local_process_id(ctx->process_id)) < 0)) { - fprintf(stderr, "Unable to allocate sufficient memory to spawn process.\n"); - AVM_ABORT(); - } - // This is a really simple hack to get the parent - child linking - // I don't really like how it is implemented but it works nicely. - // I think it should be implemented adding a parent field to Context. - if (UNLIKELY(context_link(ctx, term_from_local_process_id(new_ctx->process_id)) < 0)) { - fprintf(stderr, "Unable to allocate sufficient memory to spawn process.\n"); - AVM_ABORT(); - } - } else if (monitor_term == TRUE_ATOM) { - ref_ticks = context_monitor(new_ctx, term_from_local_process_id(ctx->process_id)); - if (UNLIKELY(ref_ticks == 0)) { - fprintf(stderr, "Unable to allocate sufficient memory to spawn process.\n"); - AVM_ABORT(); - } - } - - //TODO: check available registers count - int reg_index = 0; - term t = argv[2]; - avm_int_t size = MAX((unsigned long) term_to_int(min_heap_size_term), memory_estimate_usage(t)); + avm_int_t size = MAX(min_heap_size, memory_estimate_usage(args_term)); if (UNLIKELY(memory_ensure_free_opt(new_ctx, size, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - //TODO: new process should be terminated, however a new pid is returned anyway - fprintf(stderr, "Unable to allocate sufficient memory to spawn process.\n"); - AVM_ABORT(); + // Context was not scheduled yet, we can destroy it. + context_destroy(new_ctx); + RAISE_ERROR(OUT_OF_MEMORY_ATOM); } - while (term_is_nonempty_list(t)) { - new_ctx->x[reg_index] = memory_copy_term_tree(&new_ctx->heap, term_get_list_head(t)); + while (term_is_nonempty_list(args_term)) { + new_ctx->x[reg_index] = memory_copy_term_tree(&new_ctx->heap, term_get_list_head(args_term)); reg_index++; - t = term_get_list_tail(t); - if (!term_is_list(t)) { + args_term = term_get_list_tail(args_term); + if (!term_is_list(args_term)) { + context_destroy(new_ctx); RAISE_ERROR(BADARG_ATOM); } } - term new_pid = term_from_local_process_id(new_ctx->process_id); - - scheduler_init_ready(new_ctx); - - if (ref_ticks) { - int res_size = REF_SIZE + TUPLE_SIZE(2); - if (UNLIKELY(memory_ensure_free_opt(ctx, res_size, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { - //TODO: new process should be terminated, however a new pid is returned anyway - fprintf(stderr, "Unable to allocate sufficient memory to spawn process.\n"); - AVM_ABORT(); - } - - term ref = term_from_ref_ticks(ref_ticks, &ctx->heap); - - term pid_ref_tuple = term_alloc_tuple(2, &ctx->heap); - term_put_tuple_element(pid_ref_tuple, 0, new_pid); - term_put_tuple_element(pid_ref_tuple, 1, ref); - - return pid_ref_tuple; - } else { - return new_pid; - } + return do_spawn(ctx, new_ctx, opts_term); } static term nif_erlang_send_2(Context *ctx, int argc, term argv[]) diff --git a/src/libAtomVM/nifs.gperf b/src/libAtomVM/nifs.gperf index 65f7bbaf4..abf357650 100644 --- a/src/libAtomVM/nifs.gperf +++ b/src/libAtomVM/nifs.gperf @@ -81,8 +81,6 @@ erlang:register/2, ®ister_nif erlang:unregister/1, &unregister_nif erlang:send/2, &send_nif erlang:setelement/3, &setelement_nif -erlang:spawn/1, &spawn_fun_nif -erlang:spawn/3, &spawn_nif erlang:spawn_opt/2, &spawn_fun_opt_nif erlang:spawn_opt/4, &spawn_opt_nif erlang:system_info/1, &system_info_nif diff --git a/tests/erlang_tests/call_with_ref_test.erl b/tests/erlang_tests/call_with_ref_test.erl index e1e9aebe5..9e65468c8 100644 --- a/tests/erlang_tests/call_with_ref_test.erl +++ b/tests/erlang_tests/call_with_ref_test.erl @@ -23,7 +23,7 @@ -export([start/0, loop/1]). start() -> - Pid = spawn(call_with_ref_test, loop, [initial_state()]), + Pid = spawn_opt(call_with_ref_test, loop, [initial_state()], []), send_integer(Pid, 1), send_integer(Pid, 2), send_integer(Pid, 3), diff --git a/tests/erlang_tests/copy_terms0.erl b/tests/erlang_tests/copy_terms0.erl index 40765175c..aec0d3147 100644 --- a/tests/erlang_tests/copy_terms0.erl +++ b/tests/erlang_tests/copy_terms0.erl @@ -20,10 +20,10 @@ -module(copy_terms0). --export([start/0, loop/0, count_nestings/1]). +-export([start/0, count_nestings/1]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), {}}, Count = receive diff --git a/tests/erlang_tests/copy_terms1.erl b/tests/erlang_tests/copy_terms1.erl index 4c1f7ab89..634e328cb 100644 --- a/tests/erlang_tests/copy_terms1.erl +++ b/tests/erlang_tests/copy_terms1.erl @@ -20,10 +20,10 @@ -module(copy_terms1). --export([start/0, loop/0, count_nestings/1]). +-export([start/0, count_nestings/1]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), {{}}}, Count = receive diff --git a/tests/erlang_tests/copy_terms10.erl b/tests/erlang_tests/copy_terms10.erl index 3f720b1de..a483f903d 100644 --- a/tests/erlang_tests/copy_terms10.erl +++ b/tests/erlang_tests/copy_terms10.erl @@ -22,7 +22,6 @@ -export([ start/0, - loop/0, compute/1, compute_tree/1, a/0, @@ -52,7 +51,7 @@ ]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), z()}, Res = receive diff --git a/tests/erlang_tests/copy_terms11.erl b/tests/erlang_tests/copy_terms11.erl index 34cdec6d4..891a6aec1 100644 --- a/tests/erlang_tests/copy_terms11.erl +++ b/tests/erlang_tests/copy_terms11.erl @@ -20,10 +20,10 @@ -module(copy_terms11). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! { self(), diff --git a/tests/erlang_tests/copy_terms12.erl b/tests/erlang_tests/copy_terms12.erl index ec28e73ee..1deb2c534 100644 --- a/tests/erlang_tests/copy_terms12.erl +++ b/tests/erlang_tests/copy_terms12.erl @@ -20,10 +20,10 @@ -module(copy_terms12). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Ref = make_ref(), Pid ! {compute, Ref, self(), diff --git a/tests/erlang_tests/copy_terms13.erl b/tests/erlang_tests/copy_terms13.erl index b2bfe7fbe..2b3cae002 100644 --- a/tests/erlang_tests/copy_terms13.erl +++ b/tests/erlang_tests/copy_terms13.erl @@ -20,10 +20,10 @@ -module(copy_terms13). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Ref = make_ref(), Pid ! {compute, Ref, self(), diff --git a/tests/erlang_tests/copy_terms14.erl b/tests/erlang_tests/copy_terms14.erl index 493796ed9..57db75dfa 100644 --- a/tests/erlang_tests/copy_terms14.erl +++ b/tests/erlang_tests/copy_terms14.erl @@ -20,10 +20,10 @@ -module(copy_terms14). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Ref = make_ref(), Pid ! {det, Ref, self(), {{2, 2, 3, 9}, {1, 1, 3, 4}, {2, 0, 1, 7}, {11, 3, 4, 8}}}, Res = diff --git a/tests/erlang_tests/copy_terms15.erl b/tests/erlang_tests/copy_terms15.erl index 393f6b8c3..be345d199 100644 --- a/tests/erlang_tests/copy_terms15.erl +++ b/tests/erlang_tests/copy_terms15.erl @@ -20,11 +20,11 @@ -module(copy_terms15). --export([start/0, sort/1, insert/2, check/1, loop/0]). +-export([start/0, sort/1, insert/2, check/1]). %% erlfmt-ignore start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Ref = make_ref(), Pid ! {sort, Ref, self(), [5, 7, 9, 15, 18, 22, 4, 11, 89, 94, 1, 0, 5, 8, 9, 3, 4, 5, 35, 12, 93, 29, 39, 29, 22, 93, 23, 28, 98, 32, 32, 42, 91, 83, 38, 18, 98, 10, 12, 39, 14, 12, 93, 32, 23, diff --git a/tests/erlang_tests/copy_terms16.erl b/tests/erlang_tests/copy_terms16.erl index 55bd0af16..acbb60789 100644 --- a/tests/erlang_tests/copy_terms16.erl +++ b/tests/erlang_tests/copy_terms16.erl @@ -20,10 +20,10 @@ -module(copy_terms16). --export([start/0, find/2, loop/0]). +-export([start/0, find/2]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Ref = make_ref(), Pid ! {find, Ref, self(), [<<"Hello">>, <<"Ciao">>, <<"Hola">>, <<"Hi">>, <<"Bonjur">>]}, Res = diff --git a/tests/erlang_tests/copy_terms17.erl b/tests/erlang_tests/copy_terms17.erl index a1278d6ef..495e22ae1 100644 --- a/tests/erlang_tests/copy_terms17.erl +++ b/tests/erlang_tests/copy_terms17.erl @@ -23,7 +23,7 @@ -export([start/0, sort/1, insert/2, loop/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Ref = make_ref(), Ref2 = make_ref(), Pid ! diff --git a/tests/erlang_tests/copy_terms18.erl b/tests/erlang_tests/copy_terms18.erl index 30c74af4b..55768277a 100644 --- a/tests/erlang_tests/copy_terms18.erl +++ b/tests/erlang_tests/copy_terms18.erl @@ -22,7 +22,6 @@ -export([ start/0, - loop/0, compute/1, compute_tree/1, a/0, @@ -51,7 +50,7 @@ ]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), t()}, Res = receive diff --git a/tests/erlang_tests/copy_terms2.erl b/tests/erlang_tests/copy_terms2.erl index facb365bb..734f36dfd 100644 --- a/tests/erlang_tests/copy_terms2.erl +++ b/tests/erlang_tests/copy_terms2.erl @@ -20,10 +20,10 @@ -module(copy_terms2). --export([start/0, loop/0, count_nestings/1]). +-export([start/0, count_nestings/1]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), {{{}}}}, Count = receive diff --git a/tests/erlang_tests/copy_terms3.erl b/tests/erlang_tests/copy_terms3.erl index 25b2e381b..ab1ac499c 100644 --- a/tests/erlang_tests/copy_terms3.erl +++ b/tests/erlang_tests/copy_terms3.erl @@ -20,10 +20,10 @@ -module(copy_terms3). --export([start/0, loop/0, count_nestings/1]). +-export([start/0, count_nestings/1]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), {{{{{{}}}}}}}, Count = receive diff --git a/tests/erlang_tests/copy_terms4.erl b/tests/erlang_tests/copy_terms4.erl index 2cb306758..ddb5ac6c0 100644 --- a/tests/erlang_tests/copy_terms4.erl +++ b/tests/erlang_tests/copy_terms4.erl @@ -20,10 +20,10 @@ -module(copy_terms4). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), {[{1, 0}, {2, 1}, {3, 4}], [{4, 2}, {5, 5}, {6, 1}]}}, Res = receive diff --git a/tests/erlang_tests/copy_terms5.erl b/tests/erlang_tests/copy_terms5.erl index b5d9af213..96e864d1d 100644 --- a/tests/erlang_tests/copy_terms5.erl +++ b/tests/erlang_tests/copy_terms5.erl @@ -20,10 +20,10 @@ -module(copy_terms5). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), {[1, 2, 3], [4, 5, 6]}}, Res = receive diff --git a/tests/erlang_tests/copy_terms6.erl b/tests/erlang_tests/copy_terms6.erl index 587191dc3..a041c7652 100644 --- a/tests/erlang_tests/copy_terms6.erl +++ b/tests/erlang_tests/copy_terms6.erl @@ -20,10 +20,10 @@ -module(copy_terms6). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), [1, 2, 3]}, Res = receive diff --git a/tests/erlang_tests/copy_terms7.erl b/tests/erlang_tests/copy_terms7.erl index 41dc06b78..2e029f9b7 100644 --- a/tests/erlang_tests/copy_terms7.erl +++ b/tests/erlang_tests/copy_terms7.erl @@ -20,10 +20,10 @@ -module(copy_terms7). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), test, 5}, Res = receive diff --git a/tests/erlang_tests/copy_terms8.erl b/tests/erlang_tests/copy_terms8.erl index 5f5befe11..6d9a6d4a2 100644 --- a/tests/erlang_tests/copy_terms8.erl +++ b/tests/erlang_tests/copy_terms8.erl @@ -20,10 +20,10 @@ -module(copy_terms8). --export([start/0, loop/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {test, self(), 2}, Res = receive diff --git a/tests/erlang_tests/copy_terms9.erl b/tests/erlang_tests/copy_terms9.erl index 6b708ec85..d17f94368 100644 --- a/tests/erlang_tests/copy_terms9.erl +++ b/tests/erlang_tests/copy_terms9.erl @@ -22,7 +22,6 @@ -export([ start/0, - loop/0, compute/1, compute_tree/1, a/0, @@ -51,7 +50,7 @@ ]). start() -> - Pid = spawn(?MODULE, loop, []), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), t()}, Res = receive diff --git a/tests/erlang_tests/gen_server_like_test.erl b/tests/erlang_tests/gen_server_like_test.erl index d27d0eeb9..9d03b005c 100644 --- a/tests/erlang_tests/gen_server_like_test.erl +++ b/tests/erlang_tests/gen_server_like_test.erl @@ -76,7 +76,7 @@ start_link() -> fake_start() -> {ok, InitialState} = init(initial_state()), - spawn(?MODULE, loop, [InitialState]). + spawn_opt(?MODULE, loop, [InitialState], []). init(Initial) -> {ok, Initial}. diff --git a/tests/erlang_tests/guards3.erl b/tests/erlang_tests/guards3.erl index b42120b0b..c42795b36 100644 --- a/tests/erlang_tests/guards3.erl +++ b/tests/erlang_tests/guards3.erl @@ -24,7 +24,7 @@ start() -> Port = do_open_port("echo", []), - Pid = spawn(guards3, loop, [initial_state()]), + Pid = spawn_opt(guards3, loop, [initial_state()], []), do_something(Port) + do_something(Pid) * 3 + do_something(2) * 100. do_open_port(PortName, Param) -> diff --git a/tests/erlang_tests/is_type.erl b/tests/erlang_tests/is_type.erl index 6d967049f..4c30e9dbf 100644 --- a/tests/erlang_tests/is_type.erl +++ b/tests/erlang_tests/is_type.erl @@ -20,10 +20,10 @@ -module(is_type). --export([start/0, test_is_type/8, all_true/8, quick_exit/0]). +-export([start/0, test_is_type/8, all_true/8]). start() -> - Pid = spawn(?MODULE, quick_exit, []), + Pid = self(), test_is_type(hello, <<"hello">>, 10, [1, 2, 3], 5, Pid, make_ref(), {1, 2}). test_is_type(A, B, I, L, N, P, R, T) -> @@ -44,6 +44,3 @@ all_true(false, false, false, false, false, false, false, false) -> 0; all_true(_, _, _, _, _, _, _, _) -> -1. - -quick_exit() -> - ok. diff --git a/tests/erlang_tests/link_kill_parent.erl b/tests/erlang_tests/link_kill_parent.erl index 83c7566c2..7df586b64 100644 --- a/tests/erlang_tests/link_kill_parent.erl +++ b/tests/erlang_tests/link_kill_parent.erl @@ -20,10 +20,10 @@ -module(link_kill_parent). --export([start/0, start2/0, sum/1, proc/1]). +-export([start/0, sum/1, proc/1]). start() -> - Pid = spawn(?MODULE, start2, []), + Pid = spawn_opt(fun start2/0, []), Pid ! {monitor, self()}, CP = receive diff --git a/tests/erlang_tests/link_throw.erl b/tests/erlang_tests/link_throw.erl index af4d7ae72..f4e0aaa5c 100644 --- a/tests/erlang_tests/link_throw.erl +++ b/tests/erlang_tests/link_throw.erl @@ -20,10 +20,10 @@ -module(link_throw). --export([start/0, start2/0, sum/1, proc/1]). +-export([start/0, sum/1, proc/1]). start() -> - {Pid, Ref} = spawn_opt(?MODULE, start2, [], [monitor]), + {Pid, Ref} = spawn_opt(fun start2/0, [monitor]), Pid ! {self(), sum}, CM = receive @@ -52,7 +52,7 @@ start2() -> receive {ParentPid, sum} -> ParentPid end, - Pid = spawn(?MODULE, proc, [L]), + Pid = spawn_opt(?MODULE, proc, [L], []), erlang:link(Pid), Pid ! {self(), sum}, receive diff --git a/tests/erlang_tests/pingpong.erl b/tests/erlang_tests/pingpong.erl index 525555155..d2266b645 100644 --- a/tests/erlang_tests/pingpong.erl +++ b/tests/erlang_tests/pingpong.erl @@ -24,8 +24,8 @@ start() -> Echo = echo:start(), - Pong = spawn(?MODULE, pong, [Echo, self()]), - spawn(?MODULE, ping, [Echo, Pong]), + Pong = spawn_opt(?MODULE, pong, [Echo, self()], []), + spawn_opt(?MODULE, ping, [Echo, Pong], []), receive exit -> 1; _Any -> 0 diff --git a/tests/erlang_tests/prime.erl b/tests/erlang_tests/prime.erl index 5e2118f09..4144ebb47 100644 --- a/tests/erlang_tests/prime.erl +++ b/tests/erlang_tests/prime.erl @@ -23,9 +23,9 @@ -export([start/0, is_prime/1, calculate_list/2]). start() -> - spawn(prime, calculate_list, num_range(2, 100)), - spawn(prime, calculate_list, num_range(100, 400)), - spawn(prime, calculate_list, num_range(500, 1500)), + spawn_opt(prime, calculate_list, num_range(2, 100), []), + spawn_opt(prime, calculate_list, num_range(100, 400), []), + spawn_opt(prime, calculate_list, num_range(500, 1500), []), all_primes_test(2000) - all_primes_test(2000) + all_primes_test(2000) - diff --git a/tests/erlang_tests/prime_ext.erl b/tests/erlang_tests/prime_ext.erl index 0db5b7bea..d82a1cf0c 100644 --- a/tests/erlang_tests/prime_ext.erl +++ b/tests/erlang_tests/prime_ext.erl @@ -30,9 +30,9 @@ ]). start() -> - spawn(?MODULE, calculate_list, num_range(2, 100)), - spawn(?MODULE, calculate_list, num_range(100, 400)), - spawn(?MODULE, calculate_list, num_range(500, 1500)), + spawn_opt(?MODULE, calculate_list, num_range(2, 100), []), + spawn_opt(?MODULE, calculate_list, num_range(100, 400), []), + spawn_opt(?MODULE, calculate_list, num_range(500, 1500), []), ?MODULE:all_primes_test(2000) - ?MODULE:all_primes_test(2000) + ?MODULE:all_primes_test(2000) - diff --git a/tests/erlang_tests/send_to_dead_process.erl b/tests/erlang_tests/send_to_dead_process.erl index 15995fef9..9d43eba3e 100644 --- a/tests/erlang_tests/send_to_dead_process.erl +++ b/tests/erlang_tests/send_to_dead_process.erl @@ -20,10 +20,10 @@ -module(send_to_dead_process). --export([start/0, double_and_terminate/0]). +-export([start/0]). start() -> - Pid = spawn(?MODULE, double_and_terminate, []), + Pid = spawn_opt(fun double_and_terminate/0, []), Pid ! {self(), 10}, Result = receive diff --git a/tests/erlang_tests/sleep.erl b/tests/erlang_tests/sleep.erl index 9a749b48c..8601d4849 100644 --- a/tests/erlang_tests/sleep.erl +++ b/tests/erlang_tests/sleep.erl @@ -42,10 +42,13 @@ spawn_sleeping_processes([], Pids) -> Pids; spawn_sleeping_processes([Timeout | T], Acc) -> Parent = self(), - Pid = spawn(fun() -> - ok = sub_sleep(Timeout), - Parent ! {self(), ok} - end), + Pid = spawn_opt( + fun() -> + ok = sub_sleep(Timeout), + Parent ! {self(), ok} + end, + [] + ), spawn_sleeping_processes(T, [Pid | Acc]). wait_for_sleeping_processes([]) -> diff --git a/tests/erlang_tests/spawn_fun1.erl b/tests/erlang_tests/spawn_fun1.erl index 479dc89e9..54da47a19 100644 --- a/tests/erlang_tests/spawn_fun1.erl +++ b/tests/erlang_tests/spawn_fun1.erl @@ -23,7 +23,7 @@ -export([start/0, loop/0]). start() -> - Pid = spawn(fun loop/0), + Pid = spawn_opt(fun loop/0, []), Pid ! {self(), 21}, Double = receive diff --git a/tests/erlang_tests/spawn_fun2.erl b/tests/erlang_tests/spawn_fun2.erl index c1fa71093..70b2e9c29 100644 --- a/tests/erlang_tests/spawn_fun2.erl +++ b/tests/erlang_tests/spawn_fun2.erl @@ -25,7 +25,7 @@ start() -> Father = self(), Fun = fun() -> Father ! 33 end, - spawn(Fun), + spawn_opt(Fun, []), Result = receive Any -> Any diff --git a/tests/erlang_tests/spawn_fun3.erl b/tests/erlang_tests/spawn_fun3.erl index ca0895cbb..9ed52ab35 100644 --- a/tests/erlang_tests/spawn_fun3.erl +++ b/tests/erlang_tests/spawn_fun3.erl @@ -30,7 +30,7 @@ start() -> Pid ! sum(L) end end, - Pid = spawn(Fun), + Pid = spawn_opt(Fun, []), Pid ! {self(), sum}, receive N -> N diff --git a/tests/erlang_tests/spawn_opt_link_normal.erl b/tests/erlang_tests/spawn_opt_link_normal.erl index f4f76beee..607c9c675 100644 --- a/tests/erlang_tests/spawn_opt_link_normal.erl +++ b/tests/erlang_tests/spawn_opt_link_normal.erl @@ -20,10 +20,10 @@ -module(spawn_opt_link_normal). --export([start/0, start2/0, sum/1, proc/1]). +-export([start/0, sum/1, proc/1]). start() -> - {Pid, Ref} = spawn_opt(?MODULE, start2, [], [monitor]), + {Pid, Ref} = spawn_opt(fun start2/0, [monitor]), CM = receive N2 -> N2 diff --git a/tests/erlang_tests/state_test.erl b/tests/erlang_tests/state_test.erl index b99307db7..41cf8df88 100644 --- a/tests/erlang_tests/state_test.erl +++ b/tests/erlang_tests/state_test.erl @@ -23,7 +23,7 @@ -export([start/0, loop/1]). start() -> - Pid = spawn(state_test, loop, [initial_state()]), + Pid = spawn_opt(state_test, loop, [initial_state()], []), send_integer(Pid, 1), send_integer(Pid, 2), send_integer(Pid, 3), diff --git a/tests/erlang_tests/state_test2.erl b/tests/erlang_tests/state_test2.erl index dc611a6b1..031b33cb7 100644 --- a/tests/erlang_tests/state_test2.erl +++ b/tests/erlang_tests/state_test2.erl @@ -23,7 +23,7 @@ -export([start/0, loop/1]). start() -> - Pid = spawn(state_test2, loop, [initial_state()]), + Pid = spawn_opt(state_test2, loop, [initial_state()], []), state_test2_sender:send_msgs(Pid). initial_state() -> diff --git a/tests/erlang_tests/state_test3.erl b/tests/erlang_tests/state_test3.erl index 7aae7c19b..9e548fdb3 100644 --- a/tests/erlang_tests/state_test3.erl +++ b/tests/erlang_tests/state_test3.erl @@ -23,7 +23,7 @@ -export([start/0]). start() -> - Pid = spawn(state_test3_server, loop, [initial_state()]), + Pid = spawn_opt(state_test3_server, loop, [initial_state()], []), send_integer(Pid, 1), send_integer(Pid, 2), send_integer(Pid, 3), diff --git a/tests/erlang_tests/test_bs.erl b/tests/erlang_tests/test_bs.erl index 96e0f2f26..c7c3a0787 100644 --- a/tests/erlang_tests/test_bs.erl +++ b/tests/erlang_tests/test_bs.erl @@ -20,7 +20,7 @@ -module(test_bs). --export([start/0]). +-export([start/0, id/1]). start() -> test_pack_small_ints({2, 61, 20}, <<23, 180>>), @@ -368,12 +368,4 @@ test_large() -> true = id(X) =:= <<42:1024>>, ok. -% Prevent optimization from the compiler -id(X) -> - Self = self(), - Pid = spawn(fun() -> - Self ! {self(), X} - end), - receive - {Pid, R} -> R - end. +id(X) -> X. diff --git a/tests/erlang_tests/test_is_process_alive.erl b/tests/erlang_tests/test_is_process_alive.erl index 84fb5b932..a397f0862 100644 --- a/tests/erlang_tests/test_is_process_alive.erl +++ b/tests/erlang_tests/test_is_process_alive.erl @@ -20,18 +20,22 @@ -module(test_is_process_alive). --export([start/0, fact/1, no_loop/0]). +-export([start/0, fact/1]). start() -> - Pid = spawn(?MODULE, no_loop, []), + {Pid, Monitor} = spawn_opt(fun no_loop/0, [monitor]), A = g(is_process_alive(Pid)), Pid ! {self(), 5}, Fact = receive - Result -> + {Pid, Result} -> Result end, - sleep(50), + ok = + receive + {'DOWN', Monitor, process, Pid, normal} -> ok + after 500 -> timeout + end, case is_process_alive(Pid) of false -> Fact + A; @@ -42,9 +46,9 @@ start() -> no_loop() -> receive {Pid, AnyInteger} when is_integer(AnyInteger) -> - Pid ! fact(AnyInteger); + Pid ! {self(), fact(AnyInteger)}; {Pid, _AnyVal} -> - Pid ! error + Pid ! {self(), error} end. fact(0) -> @@ -52,11 +56,6 @@ fact(0) -> fact(N) -> N * fact(N - 1). -sleep(MSecs) -> - receive - after MSecs -> ok - end. - g(true) -> 1; g(false) -> diff --git a/tests/erlang_tests/test_min_heap_size.erl b/tests/erlang_tests/test_min_heap_size.erl index f27641437..de7ba3816 100644 --- a/tests/erlang_tests/test_min_heap_size.erl +++ b/tests/erlang_tests/test_min_heap_size.erl @@ -24,7 +24,7 @@ start() -> Self = self(), - Pid1 = spawn(?MODULE, loop, [Self]), + Pid1 = spawn_opt(?MODULE, loop, [Self], []), receive ok -> ok end, diff --git a/tests/erlang_tests/test_monitor.erl b/tests/erlang_tests/test_monitor.erl index d0e6e3532..a36890543 100644 --- a/tests/erlang_tests/test_monitor.erl +++ b/tests/erlang_tests/test_monitor.erl @@ -33,7 +33,7 @@ start() -> 0. test_monitor_normal() -> - Pid = spawn(fun() -> normal_loop() end), + Pid = spawn_opt(fun() -> normal_loop() end, []), Ref = monitor(process, Pid), Pid ! {self(), quit}, ok = @@ -51,7 +51,7 @@ test_monitor_normal() -> ok. test_monitor_demonitor() -> - Pid = spawn(fun() -> normal_loop() end), + Pid = spawn_opt(fun() -> normal_loop() end, []), Ref = monitor(process, Pid), true = demonitor(Ref), Pid ! {self(), quit}, @@ -69,10 +69,12 @@ test_monitor_demonitor() -> ok. test_monitor_noproc() -> - Pid = spawn(fun() -> ok end), - receive - after 100 -> ok - end, + {Pid, Monitor} = spawn_opt(fun() -> ok end, [monitor]), + ok = + receive + {'DOWN', Monitor, process, Pid, normal} -> ok + after 500 -> timeout + end, Ref = monitor(process, Pid), ok = receive @@ -83,7 +85,7 @@ test_monitor_noproc() -> ok. test_monitor_demonitor_flush() -> - Pid = spawn(fun() -> normal_loop() end), + Pid = spawn_opt(fun() -> normal_loop() end, []), Ref = monitor(process, Pid), Pid ! {self(), quit}, receive @@ -104,7 +106,7 @@ test_monitor_demonitor_flush() -> ok. test_monitor_demonitor_info() -> - Pid = spawn(fun() -> normal_loop() end), + Pid = spawn_opt(fun() -> normal_loop() end, []), Ref = monitor(process, Pid), true = demonitor(Ref, [info]), Pid ! {self(), quit}, @@ -123,7 +125,7 @@ test_monitor_demonitor_info() -> ok. test_monitor_demonitor_flush_info_true() -> - Pid = spawn(fun() -> normal_loop() end), + Pid = spawn_opt(fun() -> normal_loop() end, []), Ref = monitor(process, Pid), Pid ! {self(), quit}, receive @@ -144,7 +146,7 @@ test_monitor_demonitor_flush_info_true() -> ok. test_monitor_demonitor_flush_info_false() -> - Pid = spawn(fun() -> normal_loop() end), + Pid = spawn_opt(fun() -> normal_loop() end, []), Ref = monitor(process, Pid), true = demonitor(Ref, [flush, info]), Pid ! {self(), quit}, diff --git a/tests/erlang_tests/test_pids_ordering.erl b/tests/erlang_tests/test_pids_ordering.erl index 16f2a146d..678743cf7 100644 --- a/tests/erlang_tests/test_pids_ordering.erl +++ b/tests/erlang_tests/test_pids_ordering.erl @@ -23,12 +23,12 @@ -export([start/0, sort/1, insert/2, check/2]). start() -> - P1 = spawn(?MODULE, sort, [[]]), - P2 = spawn(?MODULE, sort, [[1]]), - P3 = spawn(?MODULE, sort, [[2, 1]]), - P4 = spawn(?MODULE, sort, [[3]]), - P5 = spawn(?MODULE, sort, [[4, 1]]), - P6 = spawn(?MODULE, sort, [[]]), + P1 = spawn_opt(?MODULE, sort, [[]], []), + P2 = spawn_opt(?MODULE, sort, [[1]], []), + P3 = spawn_opt(?MODULE, sort, [[2, 1]], []), + P4 = spawn_opt(?MODULE, sort, [[3]], []), + P5 = spawn_opt(?MODULE, sort, [[4, 1]], []), + P6 = spawn_opt(?MODULE, sort, [[]], []), Sorted = sort([P3, P4, P1, P5, P2]), check(Sorted, [P1, P2, P3, P4, P5]) + bool_to_n(Sorted < [P6]) * 2 + diff --git a/tests/erlang_tests/test_raise.erl b/tests/erlang_tests/test_raise.erl index 048204cab..9b4b16eb5 100644 --- a/tests/erlang_tests/test_raise.erl +++ b/tests/erlang_tests/test_raise.erl @@ -23,7 +23,7 @@ -export([start/0]). start() -> - Pid = spawn(fun() -> loop(0) end), + Pid = spawn_opt(fun() -> loop(0) end, []), Tick = fun() -> Pid ! tick end, foo = tryit( fun() -> foo end, diff --git a/tests/erlang_tests/test_refc_binaries.erl b/tests/erlang_tests/test_refc_binaries.erl index a700968b9..ec26bc2ac 100644 --- a/tests/erlang_tests/test_refc_binaries.erl +++ b/tests/erlang_tests/test_refc_binaries.erl @@ -106,7 +106,7 @@ test_send() -> Bin = create_binary(1024), ?VERIFY(MemoryBinarySize + 1024 =< erlang:memory(binary)), - Pid = erlang:spawn(fun() -> loop(#state{}) end), + Pid = spawn_opt(fun() -> loop(#state{}) end, []), PidHeapSize0 = get_heap_size(Pid), %% %% Send the process a refc binary, and check heap size @@ -134,7 +134,7 @@ test_spawn() -> %% %% Spawn a function, passing a refc binary through the args %% - Pid = erlang:spawn(?MODULE, loop, [#state{bin = Bin}]), + Pid = spawn_opt(?MODULE, loop, [#state{bin = Bin}], []), PidHeapSize0 = get_heap_size(Pid), %% %% Make sure we can get what we spawned @@ -154,7 +154,7 @@ test_spawn_fun() -> %% %% Spawn a function, passing a refc binary through the args %% - Pid = erlang:spawn(fun() -> loop(#state{bin = Bin}) end), + Pid = spawn_opt(fun() -> loop(#state{bin = Bin}) end, []), PidHeapSize0 = get_heap_size(Pid), %% %% Make sure we can get what we spawned @@ -227,7 +227,7 @@ create_string(N, Accum) -> run_test(Fun) -> Self = self(), - _Pid = spawn(fun() -> execute(Self, Fun) end), + _Pid = spawn_opt(fun() -> execute(Self, Fun) end, []), receive ok -> ok; diff --git a/tests/erlang_tests/test_selective_receive.erl b/tests/erlang_tests/test_selective_receive.erl index b38b6ec5a..d07c5bfa0 100644 --- a/tests/erlang_tests/test_selective_receive.erl +++ b/tests/erlang_tests/test_selective_receive.erl @@ -29,21 +29,30 @@ start() -> test_selective_receive() -> Self = self(), - spawn(fun() -> - Self ! three - end), - spawn(fun() -> - receive - after 250 -> ok + spawn_opt( + fun() -> + Self ! three end, - Self ! two - end), - spawn(fun() -> - receive - after 500 -> ok + [] + ), + spawn_opt( + fun() -> + receive + after 250 -> ok + end, + Self ! two end, - Self ! one - end), + [] + ), + spawn_opt( + fun() -> + receive + after 500 -> ok + end, + Self ! one + end, + [] + ), receive one -> ok @@ -59,15 +68,21 @@ test_selective_receive() -> test_selective_receive_with_timeout() -> Self = self(), - spawn(fun() -> - Self ! two - end), - spawn(fun() -> - receive - after 500 -> ok + spawn_opt( + fun() -> + Self ! two + end, + [] + ), + spawn_opt( + fun() -> + receive + after 500 -> ok + end, + Self ! one end, - Self ! one - end), + [] + ), ok = receive one -> diff --git a/tests/erlang_tests/test_send.erl b/tests/erlang_tests/test_send.erl index 6fda38ed3..dc802de52 100644 --- a/tests/erlang_tests/test_send.erl +++ b/tests/erlang_tests/test_send.erl @@ -23,7 +23,12 @@ -export([start/0]). start() -> - Dead = spawn(fun() -> ok end), + {Dead, DeadMonitor} = spawn_opt(fun() -> ok end, [monitor]), + ok = + receive + {'DOWN', DeadMonitor, process, Dead, normal} -> ok + after 500 -> timeout + end, Sent = send(self(), 32), receive Sent -> diff --git a/tests/erlang_tests/test_stacktrace.erl b/tests/erlang_tests/test_stacktrace.erl index 8655f4a71..135a67723 100644 --- a/tests/erlang_tests/test_stacktrace.erl +++ b/tests/erlang_tests/test_stacktrace.erl @@ -190,7 +190,7 @@ test_body_recursive_throw() -> test_spawned_throw() -> Self = self(), - spawn( + spawn_opt( fun() -> try do_some_stuff(blah), @@ -208,7 +208,8 @@ test_spawned_throw() -> ), Self ! Result end - end + end, + [] ), receive Result -> diff --git a/tests/erlang_tests/test_sub_binaries.erl b/tests/erlang_tests/test_sub_binaries.erl index 2490ba016..f5d7a80b3 100644 --- a/tests/erlang_tests/test_sub_binaries.erl +++ b/tests/erlang_tests/test_sub_binaries.erl @@ -137,7 +137,7 @@ test_send_sub_binary() -> Bin = create_binary(1024), BinarySize = erlang:byte_size(Bin), ?VERIFY(MemoryBinarySize + 1024 == erlang:memory(binary)), - Pid = erlang:spawn(fun() -> loop(#state{}) end), + Pid = spawn_opt(fun() -> loop(#state{}) end, []), PidHeapSize0 = get_heap_size(Pid), %% %% Send the process a refc binary, and check heap size @@ -170,7 +170,7 @@ test_spawn_sub_binary() -> %% Spawn a function, passing a refc binary through the args %% LargeSubBin = binary:part(Bin, 1, BinarySize - 1), - Pid = erlang:spawn(?MODULE, loop, [#state{bin = LargeSubBin}]), + Pid = spawn_opt(?MODULE, loop, [#state{bin = LargeSubBin}], []), PidHeapSize0 = get_heap_size(Pid), %% %% Make sure we can get what we spawned @@ -195,7 +195,7 @@ test_spawn_fun_sub_binary() -> %% Spawn a function, passing a refc binary through the args %% LargeSubBin = binary:part(Bin, 1, BinarySize - 1), - Pid = erlang:spawn(fun() -> loop(#state{bin = LargeSubBin}) end), + Pid = spawn_opt(fun() -> loop(#state{bin = LargeSubBin}) end, []), PidHeapSize0 = get_heap_size(Pid), ?VERIFY(MemoryBinarySize + 1024 == erlang:memory(binary)), %% @@ -338,7 +338,7 @@ create_string(N, Accum) -> run_test(Fun) -> Self = self(), - _Pid = spawn(fun() -> execute(Self, Fun) end), + _Pid = spawn_opt(fun() -> execute(Self, Fun) end, []), receive ok -> ok; diff --git a/tests/erlang_tests/test_system_info.erl b/tests/erlang_tests/test_system_info.erl index 834de5a32..69dee3f5c 100644 --- a/tests/erlang_tests/test_system_info.erl +++ b/tests/erlang_tests/test_system_info.erl @@ -80,7 +80,7 @@ test_process_count(_) -> test_process_count() -> Count = erlang:system_info(process_count), Self = self(), - Pid = spawn(?MODULE, loop, [Self]), + Pid = spawn_opt(?MODULE, loop, [Self], []), receive ok -> ok end, diff --git a/tests/erlang_tests/test_throw_call_ext_last.erl b/tests/erlang_tests/test_throw_call_ext_last.erl index fadb361b9..7c37d0488 100644 --- a/tests/erlang_tests/test_throw_call_ext_last.erl +++ b/tests/erlang_tests/test_throw_call_ext_last.erl @@ -38,7 +38,7 @@ test_spawn_fun_sub_binary() -> %% Spawn a function, passing a refc binary through the args %% LargeSubBin = binary:part(Bin, 1, BinarySize - 1), - Pid = erlang:spawn(fun() -> loop(#state{bin = LargeSubBin}) end), + Pid = spawn_opt(fun() -> loop(#state{bin = LargeSubBin}) end, []), PidHeapSize0 = get_heap_size(Pid), %% %% Make sure we can get what we spawned @@ -113,7 +113,7 @@ create_string(N, Accum) -> run_test(Fun) -> Self = self(), - _Pid = spawn(fun() -> execute(Self, Fun) end), + _Pid = spawn_opt(fun() -> execute(Self, Fun) end, []), receive ok -> ok; diff --git a/tests/erlang_tests/test_timeout_not_integer.erl b/tests/erlang_tests/test_timeout_not_integer.erl index f2ca54863..24217377f 100644 --- a/tests/erlang_tests/test_timeout_not_integer.erl +++ b/tests/erlang_tests/test_timeout_not_integer.erl @@ -27,8 +27,8 @@ start() -> test_infinity() -> Parent = self(), - _Pid1 = spawn(fun() -> waiter1(Parent) end), - _Pid2 = spawn(fun() -> waiter2(Parent) end), + _Pid1 = spawn_opt(fun() -> waiter1(Parent) end, []), + _Pid2 = spawn_opt(fun() -> waiter2(Parent) end, []), receive _ -> 1 % wait 2 secs as with bug we waited few ms diff --git a/tests/erlang_tests/trap_exit_flag.erl b/tests/erlang_tests/trap_exit_flag.erl index 72d324445..64c5b3699 100644 --- a/tests/erlang_tests/trap_exit_flag.erl +++ b/tests/erlang_tests/trap_exit_flag.erl @@ -20,41 +20,60 @@ -module(trap_exit_flag). --export([start/0, sum/1, proc/1]). +-export([start/0]). start() -> - L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - Pid = spawn(?MODULE, proc, [L]), false = erlang:process_flag(trap_exit, true), + ok = test_nocatch(), + ok = test_normal(), + true = erlang:process_flag(trap_exit, false), + ok = test_trap_exit_false(), + 0. + +test_nocatch() -> + Pid = spawn_opt(fun proc/0, []), erlang:link(Pid), - Pid ! {self(), sum}, - receive - {'EXIT', Pid, {{nocatch, test}, EL}} when is_pid(Pid) andalso is_list(EL) -> - 1; - {'EXIT', _, normal} = T -> - erlang:display(T), - 2; - {'EXIT', _, _} = T -> - erlang:display(T), - 3; - T when is_tuple(T) -> - erlang:display(T), - 4; - T -> - erlang:display(T), - 5 - after 30000 -> - erlang:display(timeout), - 6 - end. + Pid ! do_throw, + ok = + receive + {'EXIT', Pid, {{nocatch, test}, EL}} when is_list(EL) -> + ok; + Other -> + {unexpected, Other} + after 500 -> + timeout + end. + +test_normal() -> + Pid = spawn_opt(fun proc/0, []), + erlang:link(Pid), + Pid ! exit_normally, + ok = + receive + {'EXIT', Pid, normal} -> + ok; + Other -> + {unexpected, Other} + after 500 -> + timeout + end. + +test_trap_exit_false() -> + Pid = spawn_opt(fun proc/0, []), + erlang:link(Pid), + Pid ! exit_normally, + ok = + receive + Other -> + {unexpected, Other} + after 500 -> + ok + end. -proc(_L) -> +proc() -> receive - {_Pid, sum} -> - throw(test) + do_throw -> + throw(test); + exit_normally -> + ok end. - -sum([]) -> - 0; -sum([H | T]) -> - H + sum(T). diff --git a/tests/erlang_tests/unlink_error.erl b/tests/erlang_tests/unlink_error.erl index fd24cc361..e502ad021 100644 --- a/tests/erlang_tests/unlink_error.erl +++ b/tests/erlang_tests/unlink_error.erl @@ -51,7 +51,7 @@ start() -> start2() -> L = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - Pid = spawn(?MODULE, proc, [L]), + Pid = spawn_opt(?MODULE, proc, [L], []), erlang:link(Pid), erlang:unlink(Pid), Pid ! {self(), sum}, diff --git a/tests/erlang_tests/whereis_dead_process.erl b/tests/erlang_tests/whereis_dead_process.erl index 96fcf1bce..1ae149baa 100644 --- a/tests/erlang_tests/whereis_dead_process.erl +++ b/tests/erlang_tests/whereis_dead_process.erl @@ -34,7 +34,7 @@ test_two_names() -> test_names([foo, bar]). test_names(Names) -> - Pid = spawn(fun() -> do_register(Names) end), + Pid = spawn_opt(fun() -> do_register(Names) end, []), Monitor = monitor(process, Pid), ok = receive diff --git a/tests/libs/estdlib/CMakeLists.txt b/tests/libs/estdlib/CMakeLists.txt index 7fbf4428b..a3972b4e5 100644 --- a/tests/libs/estdlib/CMakeLists.txt +++ b/tests/libs/estdlib/CMakeLists.txt @@ -33,6 +33,7 @@ set(ERLANG_MODULES test_lists test_logger test_maps + test_spawn test_string test_proplists test_timer diff --git a/tests/libs/estdlib/test_gen_server.erl b/tests/libs/estdlib/test_gen_server.erl index 9ac933211..bf88d1b16 100644 --- a/tests/libs/estdlib/test_gen_server.erl +++ b/tests/libs/estdlib/test_gen_server.erl @@ -67,12 +67,15 @@ test_start_link() -> pong = gen_server:call(Pid, ping), pong = gen_server:call(Pid, reply_ping), - erlang:process_flag(trap_exit, true), + false = erlang:process_flag(trap_exit, true), ok = gen_server:cast(Pid, crash), - receive - {'EXIT', Pid, _Reason} -> ok - after 30000 -> timeout - end. + ok = + receive + {'EXIT', Pid, _Reason} -> ok + after 30000 -> timeout + end, + true = erlang:process_flag(trap_exit, false), + ok. test_cast() -> {ok, Pid} = gen_server:start(?MODULE, [], []), diff --git a/tests/libs/estdlib/test_gen_statem.erl b/tests/libs/estdlib/test_gen_statem.erl index 25fad2fa0..e7ddf361e 100644 --- a/tests/libs/estdlib/test_gen_statem.erl +++ b/tests/libs/estdlib/test_gen_statem.erl @@ -93,12 +93,15 @@ test_start_link() -> pong = gen_statem:call(Pid, ping), - erlang:process_flag(trap_exit, true), + false = erlang:process_flag(trap_exit, true), ok = gen_statem:cast(Pid, crash), - receive - {'EXIT', Pid, _Reason} -> ok - after 30000 -> timeout - end. + ok = + receive + {'EXIT', Pid, _Reason} -> ok + after 30000 -> timeout + end, + true = erlang:process_flag(trap_exit, false), + ok. %% %% callbacks diff --git a/tests/libs/estdlib/test_spawn.erl b/tests/libs/estdlib/test_spawn.erl new file mode 100644 index 000000000..c1af92136 --- /dev/null +++ b/tests/libs/estdlib/test_spawn.erl @@ -0,0 +1,68 @@ +% +% This file is part of AtomVM. +% +% Copyright 2023 Paul Guyot +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. +% +% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +% + +-module(test_spawn). + +-export([test/0, f/1]). + +-include("etest.hrl"). + +test() -> + ok = test_spawn(), + ok = test_spawn_link(), + ok. + +%% spawn/1, spawn/3, spawn_link/1, spawn_link/3 are not nifs but implemented +%% in erlang module. + +test_spawn() -> + Parent = self(), + Pid1 = spawn(fun() -> f(Parent) end), + ok = + receive + {Pid1, {links, []}} -> ok + after 500 -> timeout + end, + Pid2 = spawn(?MODULE, f, [Parent]), + ok = + receive + {Pid2, {links, []}} -> ok + after 500 -> timeout + end, + ok. + +test_spawn_link() -> + Parent = self(), + Pid1 = spawn_link(fun() -> f(Parent) end), + ok = + receive + {Pid1, {links, [Parent]}} -> ok + after 500 -> timeout + end, + Pid2 = spawn_link(?MODULE, f, [Parent]), + ok = + receive + {Pid2, {links, [Parent]}} -> ok + after 500 -> timeout + end, + ok. + +f(Parent) -> + Parent ! {self(), erlang:process_info(self(), links)}. diff --git a/tests/libs/estdlib/tests.erl b/tests/libs/estdlib/tests.erl index 84f7f4dc7..a5aaf8c8e 100644 --- a/tests/libs/estdlib/tests.erl +++ b/tests/libs/estdlib/tests.erl @@ -36,5 +36,6 @@ start() -> test_maps, test_proplists, test_timer, + test_spawn, test_supervisor ]). diff --git a/tests/test.c b/tests/test.c index b9941c668..fa4b52935 100644 --- a/tests/test.c +++ b/tests/test.c @@ -502,7 +502,7 @@ struct Test tests[] = { TEST_CASE_EXPECTED(link_kill_parent, 1), TEST_CASE_EXPECTED(link_throw, 1), TEST_CASE_EXPECTED(unlink_error, 1), - TEST_CASE_EXPECTED(trap_exit_flag, 1), + TEST_CASE(trap_exit_flag), TEST_CASE_COND(test_stacktrace, 0, SKIP_STACKTRACES), TEST_CASE(small_big_ext), TEST_CASE(test_crypto),