Add atomvm:posix_kill/2#2348
Conversation
|
correct commit this time around! pardon the brain-lapse Amp - never fails on pedantic things, pick and choose: PR Review —
|
|
clean Amp (not a continuation of above): PR Review —
|
| # | Severity | Area | Issue |
|---|---|---|---|
| 1 | Major | test_subprocess.erl |
Kills the wrapping shell, not sleep; test can hang/leak |
| 2 | Major | test_uart.erl |
socat still leaks on assertion/error paths |
| 3 | Minor | posix_nifs.c |
Local var signal shadows libc signal(3) |
What is correct (no change needed)
- pid_t round-trip check in
term_is_valid_pidcorrectly rejects integers
that would truncate to a different (possibly own) process. Signal <= INT_MAXboundary interm_is_signal_numberis the right cap
before casting toint; oversized signals are rejected, not truncated
(covered by the1 bsl 40test case).- Allowing negative
OsPidmatches documentedkill(2)process-group semantics.
The specSignal :: non_neg_integer()/OsPid :: integer()is consistent
with the docs — not a mismatch. || HAVE_KILLadded to theposix_errno_to_termguard is appropriate so
{error, esrch | eperm | einval}can be returned on kill-only POSIX builds.- Tolerating
{error, esrch}instop_socatis safe:eperm/einvalstill
crash thecaseexpression, so real failures are not masked.
1. Major — test_subprocess kills the shell, not sleep
test_posix_kill/0 starts a subprocess via /bin/sh -c "sleep 30".
subprocess/4 returns the /bin/sh pid, and sleep inherits the stdout pipe's
write end. Killing only the shell does not reliably kill sleep, so
read_until_eof(Fd) can block until sleep 30 exits (or the 5s select timeout
fires). This contradicts the commit's own socat fix, which uses exec
specifically so the returned pid is the target process.
--- a/tests/libs/eavmlib/test_subprocess.erl
+++ b/tests/libs/eavmlib/test_subprocess.erl
{ok, OsPid, Fd} = atomvm:subprocess(
- "/bin/sh", ["sh", "-c", "sleep 30"], undefined, [stdout]
+ "/bin/sh", ["sh", "-c", "exec sleep 30"], undefined, [stdout]
),2. Major — test_uart still leaks socat on failure paths
Each UART test calls start_socat() and only reaches stop_socat(SocatFd) at
the successful end of the function. If any assertion in between fails, the new
SIGTERM cleanup is skipped and socat keeps holding both ptys — exactly the
cascading pty-exhaustion the commit set out to prevent. The commit fixes
successful-run leaks but not failure-run leaks.
Suggested direction: guarantee cleanup with try ... after, e.g. a helper:
with_socat(Fun) ->
{SocatFd, PtyA, PtyB} = start_socat(),
try
Fun(PtyA, PtyB)
after
stop_socat(SocatFd)
end.and wrap per-test socat usage (also closing any opened Fd via after):
test_posix_tcgetattr() ->
with_socat(fun(PtyA, _PtyB) ->
{ok, Fd} = atomvm:posix_open(PtyA, [o_rdwr, o_noctty]),
try
{ok, Tio} = atomvm:posix_tcgetattr(Fd),
true = is_map(Tio),
ok
after
atomvm:posix_close(Fd)
end
end).Scope is moderate since several tests should be wrapped consistently.
3. Minor — int signal shadows libc signal(3)
In nif_atomvm_posix_kill, the local int signal shadows signal(3) from
<signal.h>. Legal C, but may trip -Wshadow and is easily avoided.
--- a/src/libAtomVM/posix_nifs.c
+++ b/src/libAtomVM/posix_nifs.c
pid_t pid = (pid_t) term_to_int64(argv[0]);
- int signal = (int) term_to_int64(argv[1]);
+ int signo = (int) term_to_int64(argv[1]);
- if (UNLIKELY(kill(pid, signal) != 0)) {
+ if (UNLIKELY(kill(pid, signo) != 0)) {
return errno_to_error_tuple_maybe_gc(ctx);
}5b353b5 to
11ae01c
Compare
Also stop leaking socat processes in tests Signed-off-by: Paul Guyot <pguyot@kallisys.net>
Also stop leaking socat processes in tests
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