[njs] QuickJS: introduced process.kill().

noreply at nginx.com noreply at nginx.com
Wed Nov 6 16:17:02 UTC 2024


details:   https://github.com/nginx/njs/commit/361a7fc60f3d0fa223160fc1864f097af849ad70
branches:  master
commit:    361a7fc60f3d0fa223160fc1864f097af849ad70
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu, 31 Oct 2024 18:15:22 -0700
description:
QuickJS: introduced process.kill().


---
 src/qjs.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/src/qjs.c b/src/qjs.c
index b529f1bb..44e9fe95 100644
--- a/src/qjs.c
+++ b/src/qjs.c
@@ -9,6 +9,14 @@
 
 #include <sys/types.h>
 #include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+
+typedef struct {
+    njs_str_t       name;
+    int             value;
+} qjs_signal_entry_t;
 
 
 extern char  **environ;
@@ -19,10 +27,37 @@ static JSValue qjs_njs_to_string_tag(JSContext *ctx, JSValueConst this_val);
 static JSValue qjs_process_to_string_tag(JSContext *ctx, JSValueConst this_val);
 static JSValue qjs_process_argv(JSContext *ctx, JSValueConst this_val);
 static JSValue qjs_process_env(JSContext *ctx, JSValueConst this_val);
+static JSValue qjs_process_kill(JSContext *ctx, JSValueConst this_val,
+    int argc, JSValueConst *argv);
 static JSValue qjs_process_pid(JSContext *ctx, JSValueConst this_val);
 static JSValue qjs_process_ppid(JSContext *ctx, JSValueConst this_val);
 
 
+/* P1990 signals from `man 7 signal` are supported */
+static qjs_signal_entry_t qjs_signals_table[] = {
+    { njs_str("ABRT"), SIGABRT },
+    { njs_str("ALRM"), SIGALRM },
+    { njs_str("CHLD"), SIGCHLD },
+    { njs_str("CONT"), SIGCONT },
+    { njs_str("FPE"),  SIGFPE  },
+    { njs_str("HUP"),  SIGHUP  },
+    { njs_str("ILL"),  SIGILL  },
+    { njs_str("INT"),  SIGINT  },
+    { njs_str("KILL"), SIGKILL },
+    { njs_str("PIPE"), SIGPIPE },
+    { njs_str("QUIT"), SIGQUIT },
+    { njs_str("SEGV"), SIGSEGV },
+    { njs_str("STOP"), SIGSTOP },
+    { njs_str("TSTP"), SIGTSTP },
+    { njs_str("TERM"), SIGTERM },
+    { njs_str("TTIN"), SIGTTIN },
+    { njs_str("TTOU"), SIGTTOU },
+    { njs_str("USR1"), SIGUSR1 },
+    { njs_str("USR2"), SIGUSR2 },
+    { njs_null_str, 0 }
+};
+
+
 static const JSCFunctionListEntry qjs_global_proto[] = {
     JS_CGETSET_DEF("njs", qjs_njs_getter, NULL),
 };
@@ -39,6 +74,7 @@ static const JSCFunctionListEntry qjs_process_proto[] = {
     JS_CGETSET_DEF("[Symbol.toStringTag]", qjs_process_to_string_tag, NULL),
     JS_CGETSET_DEF("argv", qjs_process_argv, NULL),
     JS_CGETSET_DEF("env", qjs_process_env, NULL),
+    JS_CFUNC_DEF("kill", 2, qjs_process_kill),
     JS_CGETSET_DEF("pid", qjs_process_pid, NULL),
     JS_CGETSET_DEF("ppid", qjs_process_ppid, NULL),
 };
@@ -251,6 +287,72 @@ error:
 }
 
 
+static JSValue
+qjs_process_kill(JSContext *ctx, JSValueConst this_val, int argc,
+    JSValueConst *argv)
+{
+    int                  signo, pid;
+    JSValue              val;
+    njs_str_t            name;
+    const char           *signal;
+    qjs_signal_entry_t   *entry;
+
+    if (JS_ToInt32(ctx, &pid, argv[0]) < 0) {
+        return JS_EXCEPTION;
+    }
+
+    if (JS_IsNumber(argv[1])) {
+        if (JS_ToInt32(ctx, &signo, argv[1]) < 0) {
+            return JS_EXCEPTION;
+        }
+
+        if (signo < 0 || signo >= NSIG) {
+            return JS_ThrowTypeError(ctx, "unknown signal: %d", signo);
+        }
+
+    } else {
+        val = JS_ToString(ctx, argv[1]);
+        if (JS_IsException(val)) {
+            return JS_EXCEPTION;
+        }
+
+        signal = JS_ToCString(ctx, val);
+        if (signal == NULL) {
+            JS_FreeValue(ctx, val);
+            return JS_EXCEPTION;
+        }
+
+        if (njs_strlen(signal) < 3 || memcmp(signal, "SIG", 3) != 0) {
+            JS_FreeCString(ctx, signal);
+            return JS_ThrowTypeError(ctx, "unknown signal: %s", signal);
+        }
+
+        name.start = (u_char *) signal + 3;
+        name.length = njs_strlen(signal) - 3;
+
+        for (entry = qjs_signals_table; entry->name.length != 0; entry++) {
+            if (njs_strstr_eq(&entry->name, &name)) {
+                signo = entry->value;
+                break;
+            }
+        }
+
+        JS_FreeCString(ctx, signal);
+
+        if (entry->name.length == 0) {
+            return JS_ThrowTypeError(ctx, "unknown signal: %s", signal);
+        }
+    }
+
+    if (kill(pid, signo) < 0) {
+        return JS_ThrowTypeError(ctx, "kill failed with (%d:%s)", errno,
+                                 strerror(errno));
+    }
+
+    return JS_TRUE;
+}
+
+
 static JSValue
 qjs_process_pid(JSContext *ctx, JSValueConst this_val)
 {


More information about the nginx-devel mailing list