Skip to content

Commit 2903b59

Browse files
committed
Merge pull request #2348 from pguyot/w25/posix-kill
Add `atomvm:posix_kill/2` 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 05e5846 + aaac61b commit 2903b59

16 files changed

Lines changed: 321 additions & 95 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Added
1010
- Added `filename:dirname/1`, `filename:basename/1,2`, `filename:extension/1`, `filename:rootname/1,2` and `filename:join/2`
1111
- Added `init:get_arguments/0`
12+
- Added `atomvm:posix_kill/2` to send a signal to a process, typically one started with `atomvm:subprocess/4`
1213
- Added Erlang distribution over serial (uart)
1314
- Added WASM32 JIT backend for Emscripten platform
1415
- Added `network:wifi_scan/0,1` to ESP32 network driver to scan available APs when in sta or sta+ap mode.

libs/eavmlib/src/atomvm.erl

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
posix_closedir/1,
5757
posix_readdir/1,
5858
get_creation/0,
59-
subprocess/4
59+
subprocess/4,
60+
posix_kill/2
6061
]).
6162

6263
-export_type([
@@ -518,3 +519,26 @@ get_creation() ->
518519
{ok, non_neg_integer(), posix_fd()} | {error, posix_error()}.
519520
subprocess(_Path, _Args, _Env, _Options) ->
520521
erlang:nif_error(undefined).
522+
523+
%%-----------------------------------------------------------------------------
524+
%% @param OsPid operating system process id, as returned by `subprocess/4'
525+
%% @param Signal signal number to send, e.g. 15 for SIGTERM
526+
%% @returns `ok' or an error tuple
527+
%% @doc Send a signal to a process using kill(2). Typically used to
528+
%% terminate a process started with `subprocess/4'.
529+
%%
530+
%% A return value of `ok' means kill(2) accepted the request; it does
531+
%% not guarantee that the target terminated, as the signal may be
532+
%% caught, blocked, or ignored. Signal `0' sends no signal and merely
533+
%% performs a POSIX existence/permission check.
534+
%%
535+
%% `OsPid' follows kill(2) semantics: a positive value targets a single
536+
%% process, `0' targets the caller's process group, `-1' targets every
537+
%% process the caller may signal, and a value less than `-1' targets the
538+
%% process group whose id is the absolute value.
539+
%% @end
540+
%%-----------------------------------------------------------------------------
541+
-spec posix_kill(OsPid :: integer(), Signal :: non_neg_integer()) ->
542+
ok | {error, posix_error()}.
543+
posix_kill(_OsPid, _Signal) ->
544+
erlang:nif_error(undefined).

src/libAtomVM/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ define_if_function_exists(libAtomVM fstat "sys/stat.h" PRIVATE HAVE_FSTAT)
258258
define_if_function_exists(libAtomVM unlink "unistd.h" PRIVATE HAVE_UNLINK)
259259
define_if_function_exists(libAtomVM rmdir "unistd.h" PRIVATE HAVE_RMDIR)
260260
define_if_function_exists(libAtomVM execve "unistd.h" PRIVATE HAVE_EXECVE)
261+
define_if_function_exists(libAtomVM kill "signal.h" PRIVATE HAVE_KILL)
261262
define_if_function_exists(libAtomVM tcgetattr "termios.h" PRIVATE HAVE_TCGETATTR)
262263
define_if_function_exists(libAtomVM closefrom "unistd.h" PRIVATE HAVE_CLOSEFROM)
263264
define_if_function_exists(libAtomVM getcwd "unistd.h" PUBLIC HAVE_GETCWD)

src/libAtomVM/nifs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,11 @@ DEFINE_MATH_NIF(tanh)
10331033
#define IF_HAVE_OPEN_CLOSE(expr) NULL
10341034
#define IF_HAVE_EXECVE(expr) NULL
10351035
#endif
1036+
#if HAVE_KILL
1037+
#define IF_HAVE_KILL(expr) (expr)
1038+
#else
1039+
#define IF_HAVE_KILL(expr) NULL
1040+
#endif
10361041
#if HAVE_OPEN && HAVE_CLOSE && HAVE_LSEEK
10371042
#define IF_HAVE_LSEEK(expr) (expr)
10381043
#else

src/libAtomVM/nifs.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ atomvm:posix_select_read/3, IF_HAVE_OPEN_CLOSE(&atomvm_posix_select_read_nif)
190190
atomvm:posix_select_write/3, IF_HAVE_OPEN_CLOSE(&atomvm_posix_select_write_nif)
191191
atomvm:posix_select_stop/1, IF_HAVE_OPEN_CLOSE(&atomvm_posix_select_stop_nif)
192192
atomvm:subprocess/4, IF_HAVE_EXECVE(&atomvm_subprocess_nif)
193+
atomvm:posix_kill/2, IF_HAVE_KILL(&atomvm_posix_kill_nif)
193194
atomvm:posix_seek/3, IF_HAVE_LSEEK(&atomvm_posix_seek_nif)
194195
atomvm:posix_pread/3, IF_HAVE_PREAD(&atomvm_posix_pread_nif)
195196
atomvm:posix_pwrite/3, IF_HAVE_PWRITE(&atomvm_posix_pwrite_nif)

src/libAtomVM/posix_nifs.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
#include <spawn.h>
5757
#endif
5858

59+
#if HAVE_KILL
60+
#include <limits.h>
61+
#include <signal.h>
62+
#endif
63+
5964
#include "defaultatoms.h"
6065
#include "erl_nif_priv.h"
6166
#include "globalcontext.h"
@@ -69,7 +74,7 @@ extern char **environ;
6974

7075
term posix_errno_to_term(int err, GlobalContext *glb)
7176
{
72-
#if HAVE_OPEN && HAVE_CLOSE || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_SETTIMEOFDAY)
77+
#if HAVE_OPEN && HAVE_CLOSE || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_SETTIMEOFDAY) || HAVE_KILL
7378
// These are defined in SUSv1
7479
term result;
7580
switch (err) {
@@ -954,6 +959,43 @@ static term nif_atomvm_subprocess(Context *ctx, int argc, term argv[])
954959
#endif
955960
#endif
956961

962+
#if HAVE_KILL
963+
static bool term_is_valid_pid(term t)
964+
{
965+
if (!term_is_int64(t)) {
966+
return false;
967+
}
968+
// The value must round-trip through pid_t: a larger integer would be
969+
// silently truncated and target a different (possibly own) process.
970+
int64_t value = term_to_int64(t);
971+
return ((int64_t) (pid_t) value) == value;
972+
}
973+
974+
static bool term_is_signal_number(term t)
975+
{
976+
if (!term_is_int64(t)) {
977+
return false;
978+
}
979+
int64_t value = term_to_int64(t);
980+
return value >= 0 && value <= INT_MAX;
981+
}
982+
983+
static term nif_atomvm_posix_kill(Context *ctx, int argc, term argv[])
984+
{
985+
UNUSED(argc);
986+
VALIDATE_VALUE(argv[0], term_is_valid_pid);
987+
VALIDATE_VALUE(argv[1], term_is_signal_number);
988+
989+
pid_t pid = (pid_t) term_to_int64(argv[0]);
990+
int signo = (int) term_to_int64(argv[1]);
991+
992+
if (UNLIKELY(kill(pid, signo) != 0)) {
993+
return errno_to_error_tuple_maybe_gc(ctx);
994+
}
995+
return OK_ATOM;
996+
}
997+
#endif
998+
957999
#if HAVE_MKFIFO
9581000
static term nif_atomvm_posix_mkfifo(Context *ctx, int argc, term argv[])
9591001
{
@@ -1836,6 +1878,12 @@ const struct Nif atomvm_subprocess_nif = {
18361878
};
18371879
#endif
18381880
#endif
1881+
#if HAVE_KILL
1882+
const struct Nif atomvm_posix_kill_nif = {
1883+
.base.type = NIFFunctionType,
1884+
.nif_ptr = nif_atomvm_posix_kill
1885+
};
1886+
#endif
18391887
#if HAVE_OPEN && HAVE_CLOSE && HAVE_LSEEK
18401888
const struct Nif atomvm_posix_seek_nif = {
18411889
.base.type = NIFFunctionType,

src/libAtomVM/posix_nifs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ extern const struct Nif atomvm_posix_select_stop_nif;
4747
extern const struct Nif atomvm_subprocess_nif;
4848
#endif
4949
#endif
50+
#if HAVE_KILL
51+
extern const struct Nif atomvm_posix_kill_nif;
52+
#endif
5053
#if HAVE_OPEN && HAVE_CLOSE && HAVE_LSEEK
5154
extern const struct Nif atomvm_posix_seek_nif;
5255
#endif

src/platforms/esp32/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
2828
set(HAVE_MKFIFO "" CACHE INTERNAL "Have symbol mkfifo" FORCE)
2929
# Likewise with EXECVE
3030
set(HAVE_EXECVE "" CACHE INTERNAL "Have symbol execve" FORCE)
31+
# kill links to a newlib stub but there are no OS processes to signal
32+
set(HAVE_KILL "" CACHE INTERNAL "Have symbol kill" FORCE)
3133
# Force HAVE_SOCKET
3234
# Automatically detecting it requires to put too many components include dirs
3335
# in CMAKE_REQUIRED_INCLUDES as lwip includes freetos and many esp system components

src/platforms/esp32/test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ set(HAVE_MKFIFO NO)
4141
set(HAVE_MKFIFO "" CACHE INTERNAL "Have symbol mkfifo" FORCE)
4242
set(HAVE_EXECVE NO)
4343
set(HAVE_EXECVE "" CACHE INTERNAL "Have symbol execve" FORCE)
44+
set(HAVE_KILL NO)
45+
set(HAVE_KILL "" CACHE INTERNAL "Have symbol kill" FORCE)
4446
# Force HAVE_SOCKET
4547
# Automatically detecting it requires to put too many components include dirs
4648
# in CMAKE_REQUIRED_INCLUDES as lwip includes freetos and many esp system components

src/platforms/rp2/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ set(HAVE_MKFIFO "" CACHE INTERNAL "Have symbol mkfifo" FORCE)
5454
set(HAVE_UNLINK "" CACHE INTERNAL "Have symbol unlink" FORCE)
5555
# Likewise with EXECVE
5656
set(HAVE_EXECVE "" CACHE INTERNAL "Have symbol execve" FORCE)
57+
# kill is declared in newlib's signal.h but not linkable on bare-metal
58+
set(HAVE_KILL "" CACHE INTERNAL "Have symbol kill" FORCE)
5759
# getcwd is defined in newlib header but not implemented
5860
set(HAVE_GETCWD "" CACHE INTERNAL "Have symbol getcwd" FORCE)
5961
# pread, pwrite, fsync, ftruncate, mkdir and rmdir are

0 commit comments

Comments
 (0)