Skip to content

Commit 1b3f322

Browse files
committed
Merge pull request #1646 from bettio/fix-erlang_group_leader-corner-case
Fix `erlang:group_leader/2` corner case These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 67f3706 + ab09ce5 commit 1b3f322

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

src/libAtomVM/nifs.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4083,19 +4083,33 @@ static term nif_erlang_group_leader(Context *ctx, int argc, term argv[])
40834083
VALIDATE_VALUE(leader, term_is_pid);
40844084

40854085
int local_process_id = term_to_local_process_id(pid);
4086-
Context *target = globalcontext_get_process_lock(ctx->global, local_process_id);
4087-
if (IS_NULL_PTR(target)) {
4088-
RAISE_ERROR(BADARG_ATOM);
4089-
}
4086+
if (ctx->process_id == local_process_id) {
4087+
// use a synchronous approach when updating group leader for this process
4088+
if (term_is_local_pid(leader)) {
4089+
ctx->group_leader = leader;
4090+
} else {
4091+
size_t leader_term_size = memory_estimate_usage(leader);
4092+
if (UNLIKELY(memory_ensure_free_with_roots(
4093+
ctx, leader_term_size, 1, &leader, MEMORY_CAN_SHRINK)
4094+
!= MEMORY_GC_OK)) {
4095+
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
4096+
}
4097+
ctx->group_leader = memory_copy_term_tree(&ctx->heap, leader);
4098+
}
4099+
} else {
4100+
Context *target = globalcontext_get_process_lock(ctx->global, local_process_id);
4101+
if (IS_NULL_PTR(target)) {
4102+
RAISE_ERROR(BADARG_ATOM);
4103+
}
40904104

4091-
if (term_is_local_pid(leader)) {
4092-
// We cannot put leader term on the heap
4105+
// always use signals when changing group leader of another context
4106+
// this will avoid any heap access during GC and in general avoids a number
4107+
// of annoying situations
4108+
// this will be async
40934109
mailbox_send_term_signal(target, SetGroupLeaderSignal, leader);
4094-
} else {
4095-
target->group_leader = leader;
4096-
}
40974110

4098-
globalcontext_get_process_unlock(ctx->global, target);
4111+
globalcontext_get_process_unlock(ctx->global, target);
4112+
}
40994113
return TRUE_ATOM;
41004114
}
41014115
}

0 commit comments

Comments
 (0)