Browse Source

feat: windows-信号处理

SongZihuan 3 years ago
parent
commit
c2d4f299a0
3 changed files with 70 additions and 43 deletions
  1. 3 0
      include/tool/stdio_.h
  2. 35 42
      src/core/sig.c
  3. 32 1
      src/tool/stdio_.c

+ 3 - 0
include/tool/stdio_.h

@@ -11,6 +11,9 @@ AFUN_TOOL_EXPORT bool fclear_stdin(void);
 
 #ifdef aFunWIN32_NO_CYGWIN
 
+AFUN_TOOL_EXPORT void stdio_signal_init(bool signal);
+AFUN_TOOL_EXPORT bool stdio_check_signal(void);
+
 #ifdef _MSC_VER
 #pragma warning(disable : 5105)  // 关闭 5105 的警告输出 (Windows.h中使用)
 #endif

+ 35 - 42
src/core/sig.c

@@ -23,13 +23,34 @@ struct af_SignalInfo {
 };
 
 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;
 
 
+#ifndef aFunWIN32_NO_CYGWIN
+static void aFunSigFunc(int signum);
+static void aFunSigFunc(int signum) {
+    switch (signum) {
+        case SIGINT:
+            sig_info.flat_int = 1;
+            break;
+        case SIGTERM:
+            sig_info.flat_term = 1;
+            break;
+        case SIGUSR1:
+            sig_info.flat_u1 = 1;
+            break;
+        case SIGUSR2:
+            sig_info.flat_u2 = 1;
+            break;
+        default:
+            break;
+    }
+}
+#endif
+
 void aFunSignalInit(void) {
     pthread_mutex_lock(&sig_mutex);
     if (init_sig_info) {
@@ -41,15 +62,9 @@ void aFunSignalInit(void) {
     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");
+    sig_info.sig_int = signal(SIGINT, SIG_IGN);
+    sig_info.sig_term = signal(SIGTERM, SIG_IGN);
+    stdio_signal_init(true);
 #else
     sigemptyset(&sig_info.old);
     sigemptyset(&sig_info.new);
@@ -68,9 +83,8 @@ void aFunSignalInit(void) {
     sig_info.flat_term = 0;
     sig_info.flat_u1 = 0;
     sig_info.flat_u2 = 0;
-
-    pthread_mutex_unlock(&sig_mutex);
 #endif
+    pthread_mutex_unlock(&sig_mutex);
 }
 
 void aFunSignalRecover(void) {
@@ -95,7 +109,7 @@ void aFunSignalRecover(void) {
     }
 
 #ifdef aFunWIN32_NO_CYGWIN
-
+    stdio_signal_init(false);
 #else
     if (sig_info.sig_u1 != SIG_ERR) {
         re = signal(SIGUSR1, sig_info.sig_u1);
@@ -107,35 +121,15 @@ void aFunSignalRecover(void) {
         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_info.flat_int++;
-            break;
-        case SIGTERM:
-            sig_info.flat_term++;
-            break;
-#ifndef aFunWIN32_NO_CYGWIN
-        case SIGUSR1:
-            sig_info.flat_u1++;
-            break;
-        case SIGUSR2:
-            sig_info.flat_u2++;
-            break;
 #endif
-        default:
-            break;
-    }
+    pthread_mutex_unlock(&sig_mutex);
 }
 
 static void aFuncheckSignal(void) {
     /* 该函数是内部函数, 不负责加锁 */
 #ifdef aFunWIN32_NO_CYGWIN
-
+    if (stdio_check_signal())
+        sig_info.flat_int = 1;
 #else
     for (int i = 0; i < 4; i++) {
         // 标准: sigprocmask 执行返回前必有一个未递达(如果有)的信号递达
@@ -147,7 +141,6 @@ static void aFuncheckSignal(void) {
         sigprocmask(SIG_SETMASK, &sig_info.old, NULL);  // 让信号递达
     }
     sigprocmask(SIG_BLOCK, &sig_info.new, &sig_info.old);
-
 #endif
 }
 
@@ -163,20 +156,20 @@ bool aFunGetSignal(int signum) {
 
     switch (signum) {
         case SIGINT:
-            re = sig_info.flat_int != 0;
+            re = sig_info.flat_int == 1;
             sig_info.flat_int = 0;
             break;
         case SIGTERM:
-            re = sig_info.flat_term != 0;
+            re = sig_info.flat_term == 1;
             sig_info.flat_term = 0;
             break;
-#if (defined SIGUSR1 && defined SIGUSR2)
+#ifndef aFunWIN32_NO_CYGWIN
         case SIGUSR1:
-            re = sig_info.flat_u1 != 0;
+            re = sig_info.flat_u1 == 1;
             sig_info.flat_u1 = 0;
             break;
         case SIGUSR2:
-            re = sig_info.flat_u2 != 0;
+            re = sig_info.flat_u2 == 1;
             sig_info.flat_u1 = 0;
             break;
 #endif

+ 32 - 1
src/tool/stdio_.c

@@ -8,6 +8,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include "tool.h"
+#include "signal.h"
 
 /* 注意:
  * checkStdin在Windows和Linux之前行为具有差别, 本质目标时检查缓冲区是否有内容
@@ -25,6 +26,7 @@ static char buffer[BUFF_SIZE + 1] = "";
 static size_t index = 0;
 static size_t next = 0;
 static size_t end = 0;
+volatile sig_atomic_t ctrl_c = 0;
 static pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;  // 只有 export 的函数统一处理该互斥锁
 
 static int setCursorPosition(HANDLE std_o, CONSOLE_SCREEN_BUFFER_INFO *info_, SHORT x_) {
@@ -167,7 +169,10 @@ static int checkNewInput(HANDLE *std_i, HANDLE *std_o) {
         if (record.EventType == KEY_EVENT) {
             if (!record.Event.KeyEvent.bKeyDown)
                 continue;
-            else if (record.Event.KeyEvent.wVirtualKeyCode == VK_BACK) {  // 退格
+            else if (record.Event.KeyEvent.uChar.AsciiChar == 3) {
+                ctrl_c = 1;
+                continue;
+            } else if (record.Event.KeyEvent.wVirtualKeyCode == VK_BACK) {  // 退格
                 if (backChar(std_o) == 0)
                     return -1;
                 continue;
@@ -283,6 +288,32 @@ bool fclear_stdin(void) {
     return false;
 }
 
+void stdio_signal_init(bool signal) {
+    HANDLE *std_i = GetStdHandle(STD_INPUT_HANDLE);
+    DWORD  mode;
+    GetConsoleMode(std_i, &mode);
+    if (signal)
+        mode &= ~ENABLE_PROCESSED_INPUT;
+    else
+        mode |= ENABLE_PROCESSED_INPUT;  // 系统接管 ^c
+    SetConsoleMode(std_i, mode);
+}
+
+bool stdio_check_signal(void) {
+    HANDLE *std_i = GetStdHandle(STD_INPUT_HANDLE);
+    HANDLE *std_o = GetStdHandle(STD_OUTPUT_HANDLE);
+    if (std_i == INVALID_HANDLE_VALUE || std_o == INVALID_HANDLE_VALUE) {
+        return false;
+    }
+
+    pthread_mutex_lock(&buffer_mutex);
+    fcheck_stdin(std_i, std_o);
+    bool res = ctrl_c == 1;
+    ctrl_c = 0;
+    pthread_mutex_unlock(&buffer_mutex);
+    return res;
+}
+
 int convertMultiByte(char **dest, char *str, UINT from, UINT to) {
     if (str == NULL || dest == NULL)
         return 0;