1
0
Эх сурвалжийг харах

feat: 信号不在全局范围内捕获

SongZihuan 3 жил өмнө
parent
commit
0ef9b08569

+ 1 - 0
include/core/aFunCore.h

@@ -11,6 +11,7 @@
 #include "runtime_error.h"
 
 #include "core_init.h"
+#include "sig.h"
 #include "run.h"
 #include "code.h"
 #include "bytecode.h"

+ 1 - 1
include/core/env.h

@@ -13,7 +13,7 @@ typedef struct af_ImportInfo af_ImportInfo;
 typedef void TopMsgProcessFunc(af_Message *msg, bool is_top, af_Environment *env);
 DEFINE_DLC_SYMBOL(TopMsgProcessFunc);
 
-typedef void GuardianFunc(af_Message *msg, af_Environment *env);
+typedef void GuardianFunc(bool is_guard, af_Environment *env);
 DEFINE_DLC_SYMBOL(GuardianFunc);
 
 enum GcRunTime {

+ 17 - 7
include/core/info/magic_func.h

@@ -15,13 +15,23 @@
 /* 内置环境变量 */
 #define SYS_NAME(job) "sys-" #job
 
-#define ev_sys_prefix SYS_NAME(prefix)
-#define ev_grt SYS_NAME(grt)
-#define ev_gcmax SYS_NAME(gc-max)
-#define ev_gccount SYS_NAME(gc-count)
-#define ev_exit_code SYS_NAME(exit-code)
-#define ev_argc SYS_NAME(argc)
+#define ev_sys_prefix   SYS_NAME(prefix)
+#define ev_grt          SYS_NAME(grt)
+#define ev_gcmax        SYS_NAME(gc-max)
+#define ev_gccount      SYS_NAME(gc-count)
+#define ev_exit_code    SYS_NAME(exit-code)
+#define ev_argc         SYS_NAME(argc)
 #define ev_argvx_prefix SYS_NAME(argv)
-#define ev_error_std SYS_NAME(error-std)
+#define ev_error_std    SYS_NAME(error-std)
+
+#define ev_sigint       SYS_NAME(SIGINT)
+#define ev_sigterm      SYS_NAME(SIGTERM)
+#define ev_sigu1        SYS_NAME(SIGU1)
+#define ev_sigu2        SYS_NAME(SIGU2)
+
+#define ev_sigint_cfg   ev_sigint "-config"
+#define ev_sigterm_cfg  ev_sigterm "-config"
+#define ev_sigu1_cfg    ev_sigu1 "-config"
+#define ev_sigu2_cfg    ev_sigu2 "-config"
 
 #endif //AFUN_MAGIC_FUNC_H

+ 1 - 1
include/core/info/obj_api.h

@@ -23,7 +23,7 @@ typedef void objectAPIFunc();  // 位于object.h (所有Object API函数指针
 typedef void TopMsgProcessFunc(af_Message *msg, bool is_top, af_Environment *env);  // 位于env.h
 
 /* 守护器处理函数 */
-typedef void GuardianFunc(af_Message *msg, af_Environment *env);
+typedef void GuardianFunc(bool is_guard, af_Environment *env);
 
 /* 回调C函数 */
 typedef struct CallFuncInfo CallFuncInfo;

+ 6 - 0
include/core/info/runtime_error.h

@@ -37,4 +37,10 @@
 #define API_RUN_ERROR "API-Run-Error"
 #define API_DONOT_GIVE(name) ("Object API don't give: " #name)
 
+#define SIGNAL_EXCEPTION "SIGNAL-Exception"
+#define SIGNAL_INT  "SIGINT;"
+#define SIGNAL_TERM "SIGTERM;"
+#define SIGNAL_U1   "SIGU1;"
+#define SIGNAL_U2   "SIGU2;"
+
 #endif //AFUN_RUNTIME_ERROR_H

+ 21 - 0
include/core/sig.h

@@ -0,0 +1,21 @@
+#ifndef AFUN_SIG_H
+#define AFUN_SIG_H
+#include <signal.h>
+#include "aFunCoreExport.h"
+
+struct af_SignalInfo {
+    void *sig_int;
+    void *sig_term;
+#if (defined SIGUSR1 && defined SIGUSR2)
+    void *sig_u1;
+    void *sig_u2;
+#endif
+};
+
+typedef struct af_SignalInfo af_SignalInfo;
+
+AFUN_CORE_EXPORT void aFunSignalInit(af_SignalInfo *sig_info);
+AFUN_CORE_EXPORT void aFunSignalRecover(af_SignalInfo *sig_info);
+AFUN_CORE_EXPORT bool aFunGetSignal(int signum);
+
+#endif //AFUN_SIG_H

+ 1 - 1
src/core/__env.h

@@ -185,7 +185,7 @@ struct af_ActivityTrackBack {
 typedef void TopMsgProcessFunc(af_Message *msg, bool is_top, af_Environment *env);
 NEW_DLC_SYMBOL(TopMsgProcessFunc, TopMsgProcessFunc);
 
-typedef void GuardianFunc(af_Message *msg, af_Environment *env);
+typedef void GuardianFunc(bool is_guard, af_Environment *env);
 NEW_DLC_SYMBOL(GuardianFunc, GuardianFunc);
 
 struct af_TopMsgProcess {  // 顶层msg处理器

+ 1 - 1
src/core/core_init.c

@@ -4,6 +4,7 @@
  */
 
 #include "core_init.h"
+#include "sig.h"
 #include "tool.h"
 #include <locale.h>
 
@@ -74,6 +75,5 @@ bool aFunCoreInit(aFunCoreInitInfo *info) {
         fclose(LANG_file);
     } else
         HT_initaFunGetText(NULL);
-
     return true;
 }

+ 59 - 0
src/core/env.c

@@ -77,6 +77,10 @@ static void mp_NORMAL(af_Message *msg, bool is_top, af_Environment *env);
 static void mp_ERROR(af_Message *msg, bool is_top, af_Environment *env);
 static void mp_IMPORT(af_Message *msg, bool is_top, af_Environment *env);
 
+/* 内置守护器 */
+static bool checkSignal(int signum, char *sig, char *sigcfg, char *sigerr, char err[], af_Environment *env);
+static void guardian_Signal(bool is_guard, af_Environment *env);
+
 /* 变量检查函数 */
 static bool isInfixFunc(af_Code *code, af_Environment *env);
 
@@ -745,6 +749,56 @@ static void mp_IMPORT(af_Message *msg, bool is_top, af_Environment *env) {
     freeImportInfo(ii);
 }
 
+static bool checkSignal(int signum, char *sig, char *sigcfg, char *sigerr, char err[], af_Environment *env) {
+    bool re = aFunGetSignal(signum);
+    if (!re)
+        return false;
+    int32_t *p_cfg = findEnvVarNumber(sigcfg, env);
+    int32_t cfg = 0;
+    if (p_cfg != NULL)
+        cfg = *p_cfg;
+
+    if (cfg == 0) {  // 诱发错误
+        strncat(err, sigerr, 218);
+        setEnvVarNumber(sig, 0, env);
+    } else if (cfg == 1) {  // 设置环境变量
+        setEnvVarNumber(sig, 1, env);
+    } else  // 忽略
+        setEnvVarNumber(sig, 0, env);
+
+    writeDebugLog(aFunCoreLogger, "Get %s as cfg %d", sig, cfg);
+    return true;
+}
+
+static void guardian_Signal(bool is_guard, af_Environment *env) {
+    char error_msg[218] = {NUL};
+    checkSignal(SIGINT, ev_sigint, ev_sigint_cfg, SIGNAL_INT, error_msg, env);
+    checkSignal(SIGTERM, ev_sigterm, ev_sigterm_cfg, SIGNAL_TERM, error_msg, env);
+#if (defined SIGUSR1 && defined SIGUSR2)
+    checkSignal(SIGUSR1, ev_sigu1, ev_sigu1_cfg, SIGNAL_U1, error_msg, env);
+    checkSignal(SIGUSR2, ev_sigu2, ev_sigu2_cfg, SIGNAL_U2, error_msg, env);
+#endif
+
+    if (*error_msg != NUL) {
+        // error_msg 有内容写入, 需要处理
+        if (env->activity->msg_down != NULL) {
+            af_Message *msg;
+            if (EQ_STR("NORMAL", env->activity->msg_down->type)) {
+                msg = getFirstMessage(env);
+                gc_delReference(*(af_Object **)msg->msg);
+                freeMessage(msg);
+            } else if (EQ_STR("ERROR", env->activity->msg_down->type)) {
+                msg = getFirstMessage(env);
+                freeErrorInfo(*(af_ErrorInfo **)msg->msg);
+                freeMessage(msg);
+            }
+        }
+
+        pushMessageDown(makeERRORMessage(SIGNAL_EXCEPTION, error_msg, env), env);
+    }
+
+}
+
 af_Environment *makeEnvironment(enum GcRunTime grt) {
     af_Environment *env = calloc(1, sizeof(af_Environment));
     env->esv = makeEnvVarSpace();
@@ -766,6 +820,11 @@ af_Environment *makeEnvironment(enum GcRunTime grt) {
     addTopMsgProcess("IMPORT", func3, env);
     FREE_SYMBOL(func3);
 
+    /* 设置守护器 */
+    DLC_SYMBOL(GuardianFunc) func4 = MAKE_SYMBOL(guardian_Signal, GuardianFunc);
+    addGuardian("SIGNAL", false, func4, env);
+    FREE_SYMBOL(func4);
+
     env->core->status = core_init;
     env->activity = makeTopActivity(NULL, NULL, env->core->protect, env->core->global);
     return env;

+ 12 - 8
src/core/run.c

@@ -235,7 +235,7 @@ static bool codeBlock(af_Code *code, af_Environment *env) {
 static void runGuardian(af_Environment *env) {
     for (af_Guardian *gd = env->guardian; gd != NULL; gd = gd->next) {
         if (gd->always || !env->activity->is_guard)  // guardian被标记为一直执行, 或者非is_guard模式
-            GET_SYMBOL(gd->func)(env->activity->msg_down, env);
+            GET_SYMBOL(gd->func)(env->activity->is_guard, env);
     }
 }
 
@@ -353,6 +353,10 @@ bool iterCode(af_Code *code, int mode, af_Environment *env){
     if (!iterCodeInit(code, mode, env))
         return false;
 
+    bool re = true;
+    af_SignalInfo si;
+    aFunSignalInit(&si);
+
     /*
      * 问题: 如何确保循环跳出之前, top-Activity已经被pop。(即执行释放)
      * 为什么会有这个问题: top-Activity只有在bt_next=NULL时被pop, 而循环也是在bt_next=NULL时可能被退出
@@ -374,8 +378,10 @@ bool iterCode(af_Code *code, int mode, af_Environment *env){
     /* 必须位于act_top, 且无next, 并且无msg处理才退出执行 */
     while (env->activity->type != act_top || env->activity->bt_next != NULL || env->activity->process_msg_first != 0) {
         /* 检查是否需要退出执行 */
-        if (checkStop(env))
-            goto RETURN_FALSE;
+        if (checkStop(env)) {
+            re = false;
+            goto RETURN;
+        }
 
         /* 检查gc机制 */
         checkRunGC(env);
@@ -476,12 +482,10 @@ bool iterCode(af_Code *code, int mode, af_Environment *env){
         }
     }
 
+RETURN:
+    aFunSignalRecover(&si);
     env->in_run = false;
-    return true;
-
-RETURN_FALSE:
-    env->in_run = false;
-    return false;
+    return re;
 }
 
 /*

+ 112 - 0
src/core/sig.c

@@ -0,0 +1,112 @@
+#include "aFunCore.h"
+
+static volatile sig_atomic_t sig_int = 0;  // SIGINT (Windows & *nix)
+static volatile sig_atomic_t sig_term = 0;  // SIGTERM (*nix)
+
+#if (defined SIGUSR1 && defined SIGUSR2)
+static volatile sig_atomic_t sig_u1 = 0;  // SIGUSR1 (*nix)
+static volatile sig_atomic_t sig_u2 = 0;  // SIGUSR1 (*nix)
+#endif
+
+static void aFunSigFunc(int signum);
+static void aFunSigFunc(int signum) {
+    switch (signum) {
+        case SIGINT:
+            sig_int = 1;
+            break;
+        case SIGTERM:
+            sig_term = 1;
+            break;
+#if (defined SIGUSR1 && defined SIGUSR2)
+        case SIGUSR1:
+            sig_u1 = 1;
+            break;
+        case SIGUSR2:
+            sig_u2 = 1;
+            break;
+#endif
+        default:
+            break;
+    }
+}
+
+bool aFunGetSignal(int signum) {
+    bool re = false;
+    switch (signum) {
+        case SIGINT:
+            re = sig_int == 1;
+            sig_int = 0;
+            signal(SIGINT, aFunSigFunc);
+            break;
+        case SIGTERM:
+            re = sig_term == 1;
+            sig_term = 0;
+            signal(SIGTERM, aFunSigFunc);
+            break;
+#if (defined SIGUSR1 && defined SIGUSR2)
+        case SIGUSR1:
+            re = sig_u1 == 1;
+            sig_u1 = 0;
+            signal(SIGUSR1, aFunSigFunc);
+            break;
+        case SIGUSR2:
+            re = sig_u2 == 1;
+            sig_u2 = 0;
+            signal(SIGUSR2, aFunSigFunc);
+            break;
+#endif
+        default:
+            break;
+    }
+
+    return re;
+}
+
+void aFunSignalInit(af_SignalInfo *sig_info) {
+    writeDebugLog(aFunCoreLogger, "Signal setting");
+
+    sig_int = 0;
+    sig_info->sig_int = signal(SIGINT, aFunSigFunc);
+    assertWarningLog(sig_info->sig_int != SIG_ERR, aFunCoreLogger, "SIGINT setting fail");
+
+    sig_term = 0;
+    sig_info->sig_term = signal(SIGTERM, aFunSigFunc);
+    assertWarningLog(sig_info->sig_term != SIG_ERR, aFunCoreLogger, "SIGTERM setting fail");
+
+#if (defined SIGUSR1 && defined SIGUSR2)
+    sig_u1 = 0;
+    sig_info->sig_u1 = signal(SIGUSR1, aFunSigFunc);
+    assertWarningLog(sig_info->sig_u1 != SIG_ERR, aFunCoreLogger, "SIGUSR1 setting fail");
+
+    sig_u2 = 0;
+    sig_info->sig_u2 = signal(SIGUSR2, aFunSigFunc);
+    assertWarningLog(sig_info->sig_u2 != SIG_ERR, aFunCoreLogger, "SIGUSR2 setting fail");
+#endif
+}
+
+void aFunSignalRecover(af_SignalInfo *sig_info) {
+    writeDebugLog(aFunCoreLogger, "Signal recover");
+
+    void *re = NULL;
+    if (sig_info->sig_int != SIG_ERR) {
+        re = signal(SIGINT, sig_info->sig_int);
+        assertWarningLog(re != SIG_ERR, aFunCoreLogger, "SIGINT recover fail");
+    }
+
+    if (sig_info->sig_term != SIG_ERR) {
+        re = signal(SIGTERM, sig_info->sig_term);
+        assertWarningLog(re != SIG_ERR, aFunCoreLogger, "SIGTERM recover fail");
+    }
+
+#if (defined SIGUSR1 && defined SIGUSR2)
+    if (sig_info->sig_u1 != SIG_ERR) {
+        re = signal(SIGUSR1, sig_info->sig_u1);
+        assertWarningLog(re != SIG_ERR, aFunCoreLogger, "SIGUSR1 recover fail");
+    }
+
+    if (sig_info->sig_u2 != SIG_ERR) {
+        re = signal(SIGUSR2, sig_info->sig_u2);
+        assertWarningLog(re != SIG_ERR, aFunCoreLogger, "SIGUSR2 recover fail");
+    }
+#endif
+}

+ 3 - 1
src/tool/log.c

@@ -74,8 +74,10 @@ int initLogSystem(FilePath path) {
     bool csv_head_write = (checkFile(csv_path) == 0);  // 文件不存在时才写入头部
 
     log_factory.log = fopen(log_path, "a");
-    if (log_factory.log == NULL)
+    if (log_factory.log == NULL) {
+        printf("log_path = %s\n", log_path);
         return 0;
+    }
 
     log_factory.csv = fopen(csv_path, "a");
     if (log_factory.csv == NULL)