Skip to content

Commit 6823697

Browse files
committed
Forward port changes from v0.6 release branch
Merge fixes (such as fconv issue) from release-0.6 branch into main. Also it has been added a small change to allow running beams on CLI on generic_unix.
2 parents 79bcfb9 + 729184d commit 6823697

File tree

16 files changed

+169
-35
lines changed

16 files changed

+169
-35
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212

1313
## [0.6.6] - Unreleased
1414

15+
### Added
16+
17+
- Added the ability to run beams from the CLI for Generic Unix platform (it was already possible with nodejs and emscripten).
18+
1519
### Fixed
1620

1721
- Fixed specifications of nifs from `esp_adc` module
1822
- ESP32: fix `gpio:init/1` on GPIO >= 32
23+
- Adding missing check, passing a non numeric argument to a function expecting a floating point
24+
might lead to a crash in certain situations.
25+
- Fixed several bugs in `http_server` (#1366)
26+
- Fixed generic\_unix `socket_driver` to return `{gen_tcp, closed}` when socket is closed on Linux instead of `{gen_tcp, {recv, 104}}`
27+
- Fixed a memory leak where modules were not properly destroyed when the global context is destroyd
1928

2029
## [0.6.5] - 2024-10-15
2130

libs/eavmlib/src/ahttp_client.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ transform_options(Options) ->
124124
undefined -> [{active, true} | Options];
125125
_OtherValue -> Options
126126
end,
127-
[{binary, true} | WithActive].
127+
[binary | WithActive].
128128

129129
take_parse_headers(Options) ->
130130
case proplists:get_value(parse_headers, Options) of

libs/eavmlib/src/http_server.erl

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,16 @@ find_route(Method, Path, [{Target, Mod, _Opts} | T]) ->
7373
end.
7474

7575
reply(StatusCode, ReplyBody, Conn) ->
76-
{ok, Conn} = reply(
76+
{ok, NewConn} = reply(
7777
StatusCode, ReplyBody, [<<"Content-Type: text/html\r\nConnection: close\r\n">>], Conn
7878
),
79-
Socket = proplists:get_value(socket, Conn),
79+
Socket = proplists:get_value(socket, NewConn),
8080
gen_tcp:close(Socket),
81-
ClosedConn = [{closed, true} | Conn],
81+
ClosedConn =
82+
case proplists:get_value(closed, NewConn) of
83+
undefined -> [{closed, true} | NewConn];
84+
true -> NewConn
85+
end,
8286
{ok, ClosedConn}.
8387

8488
reply(StatusCode, ReplyBody, ReplyHeaders, Conn) ->
@@ -107,13 +111,15 @@ reply(StatusCode, ReplyBody, ReplyHeaders, Conn) ->
107111
{ok, ClosedConn}
108112
end.
109113

110-
send_reply(Socket, [Chunk | Tail]) ->
114+
send_reply(Socket, [Chunk | Tail]) when is_list(Chunk) orelse is_binary(Chunk) ->
111115
case gen_tcp:send(Socket, Chunk) of
112116
ok -> send_reply(Socket, Tail);
113117
{error, _} = ErrorTuple -> ErrorTuple
114118
end;
115119
send_reply(_Socket, []) ->
116-
ok.
120+
ok;
121+
send_reply(Socket, IOData) ->
122+
gen_tcp:send(Socket, IOData).
117123

118124
code_to_status_string(200) ->
119125
<<"200 OK">>;

libs/exavmlib/lib/AVMPort.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
defmodule AVMPort do
2323
# This avoids crashing the compiler at build time
2424
@compile {:autoload, false}
25+
# This avoids compiler warnings
26+
@compile {:no_warn_undefined, [:port]}
2527
@moduledoc """
2628
This module provides an interface to communicate with AtomVM port processes.
2729
The functionality of AVMPort.call is identical to the eavmlib :port.call/2 and

src/libAtomVM/globalcontext.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ COLD_FUNC void globalcontext_destroy(GlobalContext *glb)
196196
struct ListHead *item;
197197
struct ListHead *tmp;
198198

199+
int module_index = glb->loaded_modules_count;
200+
for (int i = 0; i < module_index; i++) {
201+
module_destroy(glb->modules_by_index[i]);
202+
}
203+
199204
struct ListHead *open_avm_packs = synclist_nolock(&glb->avmpack_data);
200205
MUTABLE_LIST_FOR_EACH (item, tmp, open_avm_packs) {
201206
struct AVMPackData *avmpack_data = GET_LIST_ENTRY(item, struct AVMPackData, avmpack_head);
@@ -656,6 +661,9 @@ Module *globalcontext_get_module(GlobalContext *global, AtomString module_name_a
656661
if (UNLIKELY(!loaded_module || (globalcontext_insert_module(global, loaded_module) < 0))) {
657662
fprintf(stderr, "Failed load module: %s\n", module_name);
658663
free(module_name);
664+
if (loaded_module) {
665+
module_destroy(loaded_module);
666+
}
659667
return NULL;
660668
}
661669

src/libAtomVM/globalcontext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ term globalcontext_existing_term_from_atom_string(GlobalContext *glb, AtomString
438438
/**
439439
* @brief Inserts a module to the modules table.
440440
*
441-
* @details Inserts an already loaded module to the modules table and assigns and index to it so it can be retrieved later by name or index.
441+
* @details Inserts an already loaded module to the modules table and assigns and index to it so it can be retrieved later by name or index. The module is then owned by the global context that will destroy it when globalcontext_destroy is invoked.
442442
* @param global the global context.
443443
* @param module the module that will be added to the modules table.
444444
* @returns the module index if successful, otherwise -1.

src/libAtomVM/opcodesswitch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5912,6 +5912,9 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
59125912
#ifdef IMPL_EXECUTE_LOOP
59135913
TRACE("fconv/2 %lx, fp%i\n", src_value, freg);
59145914
context_ensure_fpregs(ctx);
5915+
if (UNLIKELY(!term_is_number(src_value))) {
5916+
RAISE_ERROR(BADARITH_ATOM);
5917+
}
59155918
ctx->fr[freg] = term_conv_to_float(src_value);
59165919
#endif
59175920

src/platforms/emscripten/src/main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ int main(int argc, char **argv)
182182
global = NULL;
183183

184184
if (main_module) {
185-
module_destroy(main_module);
186185
main_module = NULL;
187186
}
188187

src/platforms/generic_unix/lib/socket_driver.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ static EventListener *passive_recv_callback(GlobalContext *glb, EventListener *b
790790
return NULL;
791791
}
792792
SocketDriverData *socket_data = (SocketDriverData *) ctx->platform_data;
793-
if (len == 0) {
793+
if (len == 0 || (len < 0 && errno == ECONNRESET)) {
794794
// {Ref, {error, closed}}
795795
BEGIN_WITH_STACK_HEAP(12, heap);
796796
term pid = listener->pid;

src/platforms/generic_unix/main.c

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void print_help(const char *program_name)
4646
"\n"
4747
"Syntax:\n"
4848
"\n"
49-
" %s [-h] [-v] <path-to-avm-file>+\n"
49+
" %s [-h] [-v] <path-to-avm-or-beam-file>+\n"
5050
"\n"
5151
"Options:\n"
5252
"\n"
@@ -88,9 +88,7 @@ int main(int argc, char **argv)
8888

8989
GlobalContext *glb = globalcontext_new();
9090

91-
const void *startup_beam = NULL;
92-
uint32_t startup_beam_size;
93-
const char *startup_module_name;
91+
Module *startup_module = NULL;
9492

9593
for (int i = 1; i < argc; ++i) {
9694
const char *ext = strrchr(argv[i], '.');
@@ -102,50 +100,56 @@ int main(int argc, char **argv)
102100
}
103101
synclist_append(&glb->avmpack_data, &avmpack_data->avmpack_head);
104102

105-
if (IS_NULL_PTR(startup_beam)) {
103+
if (IS_NULL_PTR(startup_module)) {
104+
const void *startup_beam = NULL;
105+
const char *startup_module_name;
106+
uint32_t startup_beam_size;
106107
avmpack_find_section_by_flag(avmpack_data->data, 1, &startup_beam, &startup_beam_size, &startup_module_name);
107108

108109
if (startup_beam) {
109110
avmpack_data->in_use = true;
111+
startup_module = module_new_from_iff_binary(glb, startup_beam, startup_beam_size);
112+
if (IS_NULL_PTR(startup_module)) {
113+
fprintf(stderr, "Cannot load startup module: %s\n", startup_module_name);
114+
return EXIT_FAILURE;
115+
}
116+
globalcontext_insert_module(glb, startup_module);
117+
startup_module->module_platform_data = NULL;
110118
}
111119
}
112120

113-
} else if (i == 1 && ext && (strcmp(ext, ".beam") == 0)) {
121+
} else if (ext && (strcmp(ext, ".beam") == 0)) {
114122
MappedFile *mapped_file = mapped_file_open_beam(argv[i]);
115123
if (!iff_is_valid_beam(mapped_file->mapped)) {
116-
fprintf(stderr, "%s has invalid AVM Pack format.\n", argv[i]);
124+
fprintf(stderr, "%s has invalid beam format.\n", argv[i]);
117125
return EXIT_FAILURE;
118126
}
119-
startup_module_name = basename(argv[1]);
120-
startup_beam = mapped_file->mapped;
121-
startup_beam_size = mapped_file->size;
122-
123-
} else if (i == 1) {
124-
fprintf(stderr, "%s is not an AVM or a BEAM file.\n", argv[i]);
125-
return EXIT_FAILURE;
127+
Module *mod = module_new_from_iff_binary(glb, mapped_file->mapped, mapped_file->size);
128+
if (IS_NULL_PTR(mod)) {
129+
fprintf(stderr, "Cannot load module: %s\n", argv[i]);
130+
return EXIT_FAILURE;
131+
}
132+
globalcontext_insert_module(glb, mod);
133+
mod->module_platform_data = NULL;
134+
if (IS_NULL_PTR(startup_module) && module_search_exported_function(mod, ATOM_STR("\5", "start"), 0, glb) != 0) {
135+
startup_module = mod;
136+
}
126137

127138
} else {
128-
fprintf(stderr, "%s is not an AVM file.\n", argv[i]);
139+
fprintf(stderr, "%s is not an AVM or a BEAM file.\n", argv[i]);
129140
return EXIT_FAILURE;
130141
}
131142
}
132143

133-
if (IS_NULL_PTR(startup_beam)) {
144+
if (IS_NULL_PTR(startup_module)) {
134145
fprintf(stderr, "Unable to locate entrypoint.\n");
135146
return EXIT_FAILURE;
136147
}
137148

138-
Module *mod = module_new_from_iff_binary(glb, startup_beam, startup_beam_size);
139-
if (IS_NULL_PTR(mod)) {
140-
fprintf(stderr, "Cannot load startup module: %s\n", startup_module_name);
141-
return EXIT_FAILURE;
142-
}
143-
globalcontext_insert_module(glb, mod);
144-
mod->module_platform_data = NULL;
145149
Context *ctx = context_new(glb);
146150
ctx->leader = 1;
147151

148-
context_execute_loop(ctx, mod, "start", 0);
152+
context_execute_loop(ctx, startup_module, "start", 0);
149153

150154
term ret_value = ctx->x[0];
151155
fprintf(stderr, "Return value: ");
@@ -161,7 +165,6 @@ int main(int argc, char **argv)
161165

162166
context_destroy(ctx);
163167
globalcontext_destroy(glb);
164-
module_destroy(mod);
165168

166169
return status;
167170
}

0 commit comments

Comments
 (0)