Selaa lähdekoodia

feat: linux-信号处理

SongZihuan 3 vuotta sitten
vanhempi
sitoutus
aeafe9b6b4
10 muutettua tiedostoa jossa 176 lisäystä ja 140 poistoa
  1. 5 5
      include/core/core_init.h
  2. 2 12
      include/core/sig.h
  3. 5 1
      include/runtime/aFunlang.h
  4. 6 5
      src/core/core_init.c
  5. 2 23
      src/core/parser.c
  6. 0 4
      src/core/run.c
  7. 148 80
      src/core/sig.c
  8. 2 2
      src/main.c
  9. 5 7
      src/runtime/aFunlang.c
  10. 1 1
      test/src/run_code.c

+ 5 - 5
include/core/core_init.h

@@ -15,16 +15,16 @@ struct aFunCoreInitInfo {
     LogLevel level;
 };
 
-typedef struct aFunRunInfo aFunRunInfo;
-struct aFunRunInfo {
-    struct af_SignalInfo si;
+typedef struct aFunRunCoreInfo aFunRunCoreInfo;
+struct aFunRunCoreInfo {
+    bool signal;
 };
 
 AFUN_CORE_EXPORT extern Logger *aFunCoreLogger;
 AFUN_CORE_EXPORT bool aFunCoreInit(aFunCoreInitInfo *info);
 AFUN_CORE_EXPORT bool aFunCoreDestruct(void);
 
-AFUN_CORE_EXPORT void defineRunEnvCore(aFunRunInfo *run_env);
-AFUN_CORE_EXPORT void undefRunEnvCore(aFunRunInfo *run_env);
+AFUN_CORE_EXPORT void defineRunEnvCore(aFunRunCoreInfo *run_env);
+AFUN_CORE_EXPORT void undefRunEnvCore(aFunRunCoreInfo *run_env);
 
 #endif //AFUN_INIT_H

+ 2 - 12
include/core/sig.h

@@ -3,18 +3,8 @@
 #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 void aFunSignalInit(void);
+AFUN_CORE_EXPORT void aFunSignalRecover(void);
 AFUN_CORE_EXPORT bool aFunGetSignal(int signum);
 
 #endif //AFUN_SIG_H

+ 5 - 1
include/runtime/aFunlang.h

@@ -13,11 +13,15 @@ struct aFunInitInfo {
     LogLevel level;
 };
 
+typedef struct aFunRunInfo aFunRunInfo;
+struct aFunRunInfo {
+    bool signal;
+};
+
 AFUN_LANG_EXPORT bool aFunInit(aFunInitInfo *info);
 AFUN_LANG_EXPORT bool aFunDestruct(void);
 
 AFUN_LANG_EXPORT void defineRunEnv(aFunRunInfo *run_env);
-AFUN_LANG_EXPORT void redefRunEnvSignal(void);
 AFUN_LANG_EXPORT void undefRunEnv(aFunRunInfo *run_env);
 
 AFUN_LANG_EXPORT af_Environment *creatAFunEnvironment(int argc, char **argv);

+ 6 - 5
src/core/core_init.c

@@ -83,11 +83,12 @@ bool aFunCoreDestruct(void) {
     return true;
 }
 
-void defineRunEnvCore(aFunRunInfo *run_env) {
-    memset(&run_env->si, 0, sizeof(af_SignalInfo));
-    aFunSignalInit(&run_env->si);
+void defineRunEnvCore(aFunRunCoreInfo *run_env) {
+    if (run_env->signal)
+        aFunSignalInit();
 }
 
-void undefRunEnvCore(aFunRunInfo *run_env) {
-    aFunSignalRecover(&run_env->si);
+void undefRunEnvCore(aFunRunCoreInfo *run_env) {
+    if (run_env->signal)
+        aFunSignalRecover();
 }

+ 2 - 23
src/core/parser.c

@@ -11,6 +11,7 @@ static af_Lexical *makeLexical(void);
 static void freeLexical(af_Lexical *lex);
 static af_Syntactic *makeSyntactic(void);
 static void freeSyntactic(af_Syntactic *syntactic);
+static bool getStdinSignalFunc(void);
 
 af_Parser *makeParser(FilePath file, DLC_SYMBOL(readerFunc) read_func, DLC_SYMBOL(destructReaderFunc) destruct_func,
                       size_t data_size){
@@ -183,28 +184,8 @@ struct readerDataStdin {
     size_t len;
 };
 
-static volatile sig_atomic_t stdin_interrupt = 0;
-
-static void stdinSignalFunc(int signum) {
-    stdin_interrupt = 1;
-}
-
-static void setStdinSignalFunc(struct readerDataStdin *data) {
-    data->sig_int = signal(SIGINT, stdinSignalFunc);
-    data->sig_term = signal(SIGTERM, stdinSignalFunc);
-}
-
-static void resetStdinSignalFunc(void) {
-    stdin_interrupt = 0;
-    signal(SIGINT, stdinSignalFunc);
-    signal(SIGTERM, stdinSignalFunc);
-}
-
 static bool getStdinSignalFunc(void) {
-    bool re = stdin_interrupt == 1;
-    stdin_interrupt = 0;
-    resetStdinSignalFunc();
-    return re;
+    return aFunGetSignal(SIGINT) || aFunGetSignal(SIGTERM);
 }
 
 static size_t readFuncStdin(struct readerDataStdin *data, char *dest, size_t len, int *mode) {
@@ -273,8 +254,6 @@ static void destructStdin(struct readerDataStdin *data) {
 }
 
 static void initStdinReader(af_Parser *parser, struct readerDataStdin *data) {
-    stdin_interrupt = 0;
-    setStdinSignalFunc(data);
     data->parser = parser;
 }
 

+ 0 - 4
src/core/run.c

@@ -350,10 +350,7 @@ static bool checkStop(af_Environment *env) {
 bool iterCode(af_Code *code, int mode, af_Environment *env){
     if (!iterCodeInit(code, mode, env))
         return false;
-
     bool re = true;
-    aFunRunInfo ri;
-    defineRunEnvCore(&ri);
 
     /*
      * 问题: 如何确保循环跳出之前, top-Activity已经被pop。(即执行释放)
@@ -483,7 +480,6 @@ bool iterCode(af_Code *code, int mode, af_Environment *env){
     }
 
 RETURN:
-    undefRunEnvCore(&ri);
     env->in_run = false;
     return re;
 }

+ 148 - 80
src/core/sig.c

@@ -1,29 +1,130 @@
 #include "aFunCore.h"
 #include "__sig.h"
+#include "pthread.h"
 
-static volatile sig_atomic_t sig_int = 0;  // SIGINT (Windows & *nix)
-static volatile sig_atomic_t sig_term = 0;  // SIGTERM (*nix)
+struct af_SignalInfo {
+    void *sig_int;
+    void *sig_term;
 
-#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)
+    volatile sig_atomic_t flat_int;  // SIGUSR1 (*nix)
+    volatile sig_atomic_t flat_term;  // SIGUSR1 (*nix)
+
+#ifdef aFunWIN32_NO_CYGWIN
+
+#else
+    volatile sig_atomic_t flat_u1;  // SIGUSR1 (*nix)
+    volatile sig_atomic_t flat_u2;  // SIGUSR1 (*nix)
+
+    void *sig_u1;
+    void *sig_u2;
+    sigset_t new;
+    sigset_t old;
 #endif
+};
 
+static void aFuncheckSignal(void);
 static void aFunSigFunc(int signum);
+typedef struct af_SignalInfo af_SignalInfo;
+af_SignalInfo sig_info;
+bool init_sig_info = false;
+pthread_mutex_t sig_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+void aFunSignalInit(void) {
+    pthread_mutex_lock(&sig_mutex);
+    if (init_sig_info) {
+        pthread_mutex_unlock(&sig_mutex);
+        writeWarningLog(aFunCoreLogger, "Double signal init");
+        return;
+    }
+
+    writeDebugLog(aFunCoreLogger, "Signal init");
+    init_sig_info = true;
+#ifdef aFunWIN32_NO_CYGWIN
+    sig_info->sig_int = signal(SIGINT, aFunSigFunc);
+    if (aFunSigFunc != sig_info->sig_int)
+        sig_int = 0;
+    assertWarningLog(sig_info->sig_int != SIG_ERR, aFunCoreLogger, "SIGINT setting fail");
+
+    sig_info->sig_term = signal(SIGTERM, aFunSigFunc);
+    if (aFunSigFunc != sig_info->sig_term)
+        sig_term = 0;
+    assertWarningLog(sig_info->sig_term != SIG_ERR, aFunCoreLogger, "SIGTERM setting fail");
+#else
+    sigemptyset(&sig_info.old);
+    sigemptyset(&sig_info.new);
+    sigaddset(&sig_info.new, SIGINT);
+    sigaddset(&sig_info.new, SIGTERM);
+    sigaddset(&sig_info.new, SIGUSR1);
+    sigaddset(&sig_info.new, SIGUSR2);
+    sigprocmask(SIG_BLOCK, &sig_info.new, &sig_info.old);
+
+    sig_info.sig_int = signal(SIGINT, aFunSigFunc);
+    sig_info.sig_term = signal(SIGTERM, aFunSigFunc);
+    sig_info.sig_u1 = signal(SIGUSR1, aFunSigFunc);
+    sig_info.sig_u2 = signal(SIGUSR2, aFunSigFunc);
+
+    sig_info.flat_int = 0;
+    sig_info.flat_term = 0;
+    sig_info.flat_u1 = 0;
+    sig_info.flat_u2 = 0;
+
+    pthread_mutex_unlock(&sig_mutex);
+#endif
+}
+
+void aFunSignalRecover(void) {
+    pthread_mutex_lock(&sig_mutex);
+    if (!init_sig_info) {
+        pthread_mutex_unlock(&sig_mutex);
+        writeWarningLog(aFunCoreLogger, "Signal recover before init");
+        return;
+    }
+
+    void *re = NULL;
+    writeDebugLog(aFunCoreLogger, "Signal recover");
+
+    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");
+    }
+
+#ifdef aFunWIN32_NO_CYGWIN
+
+#else
+    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");
+    }
+    sigprocmask(SIG_SETMASK, &sig_info.old, NULL);
+    pthread_mutex_unlock(&sig_mutex);
+#endif
+}
+
 static void aFunSigFunc(int signum) {
     switch (signum) {
         case SIGINT:
-            sig_int = 1;
+            sig_info.flat_int++;
             break;
         case SIGTERM:
-            sig_term = 1;
+            sig_info.flat_term++;
             break;
-#if (defined SIGUSR1 && defined SIGUSR2)
+#ifndef aFunWIN32_NO_CYGWIN
         case SIGUSR1:
-            sig_u1 = 1;
+            sig_info.flat_u1++;
             break;
         case SIGUSR2:
-            sig_u2 = 1;
+            sig_info.flat_u2++;
             break;
 #endif
         default:
@@ -31,91 +132,58 @@ static void aFunSigFunc(int signum) {
     }
 }
 
+static void aFuncheckSignal(void) {
+    /* 该函数是内部函数, 不负责加锁 */
+#ifdef aFunWIN32_NO_CYGWIN
+
+#else
+    for (int i = 0; i < 4; i++) {
+        // 标准: sigprocmask 执行返回前必有一个未递达(如果有)的信号递达
+        // 循环 count 次, 确保信号都递达
+        signal(SIGINT, aFunSigFunc);
+        signal(SIGTERM, aFunSigFunc);
+        signal(SIGUSR1, aFunSigFunc);
+        signal(SIGUSR2, aFunSigFunc);
+        sigprocmask(SIG_SETMASK, &sig_info.old, NULL);  // 让信号递达
+    }
+    sigprocmask(SIG_BLOCK, &sig_info.new, &sig_info.old);
+
+#endif
+}
+
 bool aFunGetSignal(int signum) {
+    pthread_mutex_lock(&sig_mutex);
+    if (!init_sig_info) {
+        pthread_mutex_unlock(&sig_mutex);
+        return false;
+    }
+
     bool re = false;
+    aFuncheckSignal();
+
     switch (signum) {
         case SIGINT:
-            re = sig_int == 1;
-            sig_int = 0;
-            signal(SIGINT, aFunSigFunc);
+            re = sig_info.flat_int != 0;
+            sig_info.flat_int = 0;
             break;
         case SIGTERM:
-            re = sig_term == 1;
-            sig_term = 0;
-            signal(SIGTERM, aFunSigFunc);
+            re = sig_info.flat_term != 0;
+            sig_info.flat_term = 0;
             break;
 #if (defined SIGUSR1 && defined SIGUSR2)
         case SIGUSR1:
-            re = sig_u1 == 1;
-            sig_u1 = 0;
-            signal(SIGUSR1, aFunSigFunc);
+            re = sig_info.flat_u1 != 0;
+            sig_info.flat_u1 = 0;
             break;
         case SIGUSR2:
-            re = sig_u2 == 1;
-            sig_u2 = 0;
-            signal(SIGUSR2, aFunSigFunc);
+            re = sig_info.flat_u2 != 0;
+            sig_info.flat_u1 = 0;
             break;
 #endif
         default:
             break;
     }
 
+    pthread_mutex_unlock(&sig_mutex);
     return re;
-}
-
-void aFunSignalInit(af_SignalInfo *sig_info) {
-    struct af_SignalInfo tmp;
-    if (sig_info == NULL)
-        sig_info = &tmp;
-    else
-        writeDebugLog(aFunCoreLogger, "Signal setting");  // 只有有sig_info的才显示此句
-
-    sig_info->sig_int = signal(SIGINT, aFunSigFunc);
-    if (aFunSigFunc != sig_info->sig_int)
-        sig_int = 0;
-    assertWarningLog(sig_info->sig_int != SIG_ERR, aFunCoreLogger, "SIGINT setting fail");
-
-    sig_info->sig_term = signal(SIGTERM, aFunSigFunc);
-    if (aFunSigFunc != sig_info->sig_term)
-        sig_term = 0;
-    assertWarningLog(sig_info->sig_term != SIG_ERR, aFunCoreLogger, "SIGTERM setting fail");
-
-#if (defined SIGUSR1 && defined SIGUSR2)
-    sig_info->sig_u1 = signal(SIGUSR1, aFunSigFunc);
-    if (aFunSigFunc != sig_info->sig_u1)
-        sig_u1 = 0;
-    assertWarningLog(sig_info->sig_u1 != SIG_ERR, aFunCoreLogger, "SIGUSR1 setting fail");
-
-    sig_info->sig_u2 = signal(SIGUSR2, aFunSigFunc);
-    if (aFunSigFunc != sig_info->sig_u2)
-        sig_u2 = 0;
-    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
-}
+}

+ 2 - 2
src/main.c

@@ -199,7 +199,7 @@ static int mainRun(ff_FFlags *ff) {
     char **argv = NULL;
     int argc = ff_get_process_argv(&argv, ff);
     af_Environment *env;
-    aFunRunInfo ri = {0};
+    aFunRunInfo ri = {.signal=true};
     defineRunEnv(&ri);
 
     if (argc == 0) {
@@ -305,7 +305,7 @@ static int mainCL(ff_FFlags *ff) {
         argv[i] = text;
 
     af_Environment *env = creatAFunEnvironment(argc, argv);
-    aFunRunInfo ri = {0};
+    aFunRunInfo ri = {.signal=true};
     defineRunEnv(&ri);  // 由aFunCore提前接管
 
     if (rl != NULL)

+ 5 - 7
src/runtime/aFunlang.c

@@ -47,19 +47,17 @@ bool aFunDestruct(void) {
  * 目标: 运行前的初始化
  */
 void defineRunEnv(aFunRunInfo *run_env) {
-    defineRunEnvCore(run_env);
-}
-
-void redefRunEnvSignal(void) {
-    aFunSignalInit(NULL);
+    aFunRunCoreInfo core_info = {.signal=run_env->signal};
+    defineRunEnvCore(&core_info);
 }
 
 /*
  * 函数名: undefRunEnv
- * 目标: 取消运行前的初始
+ * 目标: 取消运行前的初始
  */
 void undefRunEnv(aFunRunInfo *run_env) {
-    undefRunEnvCore(run_env);
+    aFunRunCoreInfo core_info = {.signal=run_env->signal};
+    undefRunEnvCore(&core_info);
 }
 
 

+ 1 - 1
test/src/run_code.c

@@ -414,7 +414,7 @@ INIT_ERROR:
 
 
     af_Environment *env = creatAFunEnvironment(0, NULL);
-    aFunRunInfo ri = {0};
+    aFunRunInfo ri = {.signal=true};
     defineRunEnv(&ri);
 
     if(!pushLiteralRegex("data.*", "func", true, env)) {