Bladeren bron

feat: 处理aFunlang的信号

SongZihuan 3 jaren geleden
bovenliggende
commit
dd3931ec6b
11 gewijzigde bestanden met toevoegingen van 83 en 93 verwijderingen
  1. 1 3
      include/core/parser.h
  2. 2 1
      include/runtime/aFunlang.h
  3. 1 0
      include/tool/stdio_.h
  4. 2 1
      lang/tr/zh_cn.py
  5. 55 6
      src/core/parser.c
  6. 5 1
      src/core/sig.c
  7. 9 23
      src/main.c
  8. 0 39
      src/main_signal.c
  9. 0 15
      src/main_signal.h
  10. 7 3
      src/runtime/aFunlang.c
  11. 1 1
      src/tool/stdio_.c

+ 1 - 3
include/core/parser.h

@@ -8,8 +8,6 @@
 #define SYNTACTIC_MAX_DEEP (1000)
 typedef struct af_Parser af_Parser;
 
-typedef bool ParserStdinInterruptFunc(void);
-
 #define STDIN_MAX_SIZE (1024)
 
 /* Parser 创建与释放 */
@@ -18,7 +16,7 @@ makeParser(DLC_SYMBOL(readerFunc) read_func, DLC_SYMBOL(destructReaderFunc) dest
 AFUN_CORE_EXPORT void freeParser(af_Parser *parser);
 AFUN_CORE_EXPORT af_Parser *makeParserByString(char *str, bool free_str);
 AFUN_CORE_EXPORT af_Parser *makeParserByFile(FilePath path);
-AFUN_CORE_EXPORT af_Parser *makeParserByStdin(ParserStdinInterruptFunc *interrupt);
+AFUN_CORE_EXPORT af_Parser *makeParserByStdin(void);
 
 /* Parser 相关操作 */
 AFUN_CORE_EXPORT af_Code *parserCode(FilePath file, af_Parser *parser);

+ 2 - 1
include/runtime/aFunlang.h

@@ -14,6 +14,7 @@ struct aFunInitInfo {
 
 AFUN_LANG_EXPORT bool aFunInit(aFunInitInfo *info);
 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);
@@ -22,7 +23,7 @@ AFUN_LANG_EXPORT void destructAFunEnvironment(af_Environment *env);
 /* 源文件运行 */
 AFUN_LANG_EXPORT int runCodeFromString(char *code, char *string_name, int mode, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromFileSource(FilePath file, bool save_afb, FilePath save_path, int mode, af_Environment *env);
-AFUN_LANG_EXPORT int runCodeFromStdin(char *name, ParserStdinInterruptFunc *interrupt, af_Environment *env);
+AFUN_LANG_EXPORT int runCodeFromStdin(char *name, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromMemory(af_Code *code, int mode, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromFileByte(FilePath file, int mode, af_Environment *env);
 AFUN_LANG_EXPORT int runCodeFromFile(FilePath file, bool save_afb, int mode, af_Environment *env);

+ 1 - 0
include/tool/stdio_.h

@@ -6,6 +6,7 @@ AFUN_TOOL_EXPORT int fgets_stdin(char **dest, int len);
 AFUN_TOOL_EXPORT bool checkStdin(void);
 
 #define CLEAR_FERROR(file) (ferror(file) && (clearerr(file), ferror(file)))  /* 出现错误后尝试修复, 并再次检查 */
+#define CLEAR_STDIN(file) ((ferror(stdin) || feof(stdin)) && (clearerr(stdin), (ferror(stdin) || feof(stdin))))
 
 #ifdef aFunWIN32_NO_CYGWIN
 AFUN_TOOL_EXPORT int fgetchar_stdin(void);

+ 2 - 1
lang/tr/zh_cn.py

@@ -43,4 +43,5 @@ run_file_aun_aub_e = '运行的文件不是.aun或.aub文件'
 run_file_not_exists_e = '需要运行的文件不存在'
 build_in_aun_e = '被编译的文件不是.aun文件'
 build_out_aub_e = '编译输出的文件不是.aun文件'
-build_error_e = '编译失败'
+build_error_e = '编译失败'
+Interrupt_n = '中断'

+ 55 - 6
src/core/parser.c

@@ -4,6 +4,7 @@
  */
 
 #include "aFunCore.h"
+#include "tool.h"
 #include "__parser.h"
 
 static af_Lexical *makeLexical(void);
@@ -148,15 +149,47 @@ af_Parser *makeParserByFile(FilePath path){
 
 struct readerDataStdin {
     bool no_first;
-    bool (*interrupt)(void);  // 中断函数
+
+    void *sig_int;
+    void *sig_term;
 
     char *data;
     size_t index;
     size_t len;
 };
 
+static 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;
+}
+
 static size_t readFuncStdin(struct readerDataStdin *data, char *dest, size_t len, bool *read_end) {
     if (data->index == data->len) {  // 读取内容
+        if (CLEAR_STDIN()) {
+            writeErrorLog(aFunCoreLogger, "The strin IO error, %d, %d", ferror(stdin), feof(stdin));
+            *read_end = true;
+            return 0;
+        }
+
         if (data->no_first)
             fputs("\r.... ", stdout);
         else
@@ -166,15 +199,22 @@ static size_t readFuncStdin(struct readerDataStdin *data, char *dest, size_t len
         free(data->data);
 
         while (!checkStdin()) {  // 无内容则一直循环等到
-            /* 检查信号中断 */
-            if (data->interrupt != NULL && data->interrupt()) {  // 设置了中断函数, 并且该函数返回0
-                printf("\rInterrupt\n");
+            if (getStdinSignalFunc()) {  // 设置了中断函数, 并且该函数返回0
+                printf_stdout(0, "\n %s \n", HT_aFunGetText(Interrupt_n, "Interrupt"));
                 *read_end = true;
                 return 0;
             }
         }
 
         int ch = fgetchar_stdin();
+        if (ferror(stdin) || feof(stdin)) {  // 被中断
+            clearerr(stdin);
+            resetStdinSignalFunc();
+            printf_stdout(0, "\n %s \n", HT_aFunGetText(Interrupt_n, "Interrupt"));
+            *read_end = true;
+            return 0;
+        }
+
         if (ch == '\n' || ch == EOF) {
             /* 读取结束 */
             *read_end = true;
@@ -202,16 +242,25 @@ static size_t readFuncStdin(struct readerDataStdin *data, char *dest, size_t len
 
 static void destructStdin(struct readerDataStdin *data) {
     free(data->data);
+    if (data->sig_int != SIG_ERR)
+        signal(SIGINT, data->sig_int);
+    if (data->sig_term != SIG_ERR)
+        signal(SIGTERM, data->sig_term);
+}
+
+static void initStdin(struct readerDataStdin *data) {
+    stdin_interrupt = 0;
+    setStdinSignalFunc(data);
 }
 
-af_Parser *makeParserByStdin(ParserStdinInterruptFunc *interrupt){
+af_Parser *makeParserByStdin(){
     if (CLEAR_FERROR(stdin))
         return NULL;
 
     DLC_SYMBOL(readerFunc) read_func = MAKE_SYMBOL(readFuncStdin, readerFunc);
     DLC_SYMBOL(destructReaderFunc) destruct = MAKE_SYMBOL(destructStdin, destructReaderFunc);
     af_Parser *parser = makeParser(read_func, destruct, sizeof(struct readerDataStdin));
-    ((struct readerDataStdin *)parser->reader->data)->interrupt = interrupt;
+    initStdin(parser->reader->data);
     initParser(parser);
     FREE_SYMBOL(read_func);
     FREE_SYMBOL(destruct);

+ 5 - 1
src/core/sig.c

@@ -64,7 +64,11 @@ bool aFunGetSignal(int signum) {
 }
 
 void aFunSignalInit(af_SignalInfo *sig_info) {
-    writeDebugLog(aFunCoreLogger, "Signal setting");
+    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)

+ 9 - 23
src/main.c

@@ -3,7 +3,6 @@
 #include "aFun.h"
 #include "main_run.h"
 #include "main_build.h"
-#include "main_signal.h"
 
 ff_defArg(help, false)
                 ff_argRule('h', help, not, 'h')
@@ -37,7 +36,7 @@ static const char *name = NULL;
 static int mainHelp(ff_FFlags *ff);
 static void printVersion(void);
 static void printHelp(void);
-static bool stdin_interrupt(void);
+static bool stdin_interrupt(int f);
 static int mainRun(ff_FFlags *ff);
 static int mainCL(ff_FFlags *ff);
 static int mainBuild(ff_FFlags *ff);
@@ -46,8 +45,6 @@ char *base_path = NULL;
 static Logger aFunlangLogger_;
 Logger *aFunlangLogger = &aFunlangLogger_;
 
-#define CHECK_SIGNAL() do{if (getSignal()){writeErrorLog(aFunlangLogger, "SIGINT");return EXIT_FAILURE;}}while(0)
-
 void freeBaseName(void) {
     free(base_path);
 }
@@ -134,6 +131,7 @@ static int mainHelp(ff_FFlags *ff) {
     char *text = NULL;
     int mark;
     bool have_opt = false;
+    /* 无信号处理 */
 
     while (1) {
         mark = ff_getopt(&text, ff);
@@ -163,13 +161,6 @@ out:
     return EXIT_SUCCESS;
 }
 
-static bool stdin_interrupt(void) {
-    bool re = getSignal();
-    if (re)
-        writeInfoLog(aFunlangLogger, "Signal Interrupt");
-    return re;
-}
-
 static int mainRun(ff_FFlags *ff) {
     int exit_code;
     char **argv = NULL;
@@ -183,12 +174,12 @@ static int mainRun(ff_FFlags *ff) {
         env = creatAFunEnvironment(0, NULL);
         printWelcomeInfo();
         do {
-            if (CLEAR_FERROR(stdin) || feof(stdin)) {
+            if (ferror(stdin) || feof(stdin)) {  // 错误应在实际程序中处理, 若在此仍处于错误状态则直接返回
                 writeErrorLog(aFunlangLogger, "stdin error/eof");
                 exit_code = -1;
                 break;
             }
-            exit_code = runCodeFromStdin("stdin", stdin_interrupt, env);
+            exit_code = runCodeFromStdin("stdin", env);
         } while (isCoreExit(env) != 1);  // exit_code == -1 表示stdin出现错误
         destructAFunEnvironment(env);
     } else {
@@ -281,8 +272,6 @@ static int mainCL(ff_FFlags *ff) {
     for (int i = 0; ff_getopt_wild_after(&text, ff); i++)
         argv[i] = text;
 
-    CHECK_SIGNAL();
-
     af_Environment *env = creatAFunEnvironment(argc, argv);
     aFunRunInfo ri = {0};
     defineRunEnv(&ri);  // 由aFunCore提前接管
@@ -293,12 +282,12 @@ static int mainCL(ff_FFlags *ff) {
     if (command_line && isCoreExit(env) != 1) {
         printWelcomeInfo();
         do {
-            if (CLEAR_FERROR(stdin) || feof(stdin)) {
+            if (ferror(stdin) || feof(stdin)) {  // 错误应在实际程序中处理, 若在此仍处于错误状态则直接返回
                 writeErrorLog(aFunlangLogger, "stdin error/eof");
                 exit_code = -1;
                 break;
             }
-            exit_code = runCodeFromStdin("stdin", stdin_interrupt, env);
+            exit_code = runCodeFromStdin("stdin", env);
         } while (isCoreExit(env) != 1);
     }
 
@@ -321,6 +310,7 @@ static int mainBuild(ff_FFlags *ff) {
     char *path = NULL;
     bool force = false;
     int mark;
+    int exit_code = 0;
 
     while (1) {
         mark = ff_getopt(&text, ff);
@@ -371,20 +361,16 @@ out:
             goto error;
         }
 
-        CHECK_SIGNAL();  // 检查信号
         return buildFileOutput(out_put, in, force);
     } else if (path != NULL) {
-        int exit_code = 0;
         while (ff_getopt_wild(&text, ff) && exit_code == 0)
             exit_code = buildFileToPath(path, text, force);
         return exit_code;
     }
 
-    int exit_code = 0;
-    while (ff_getopt_wild(&text, ff) && exit_code == 0) {
-        CHECK_SIGNAL();  // 检查信号
+    while (ff_getopt_wild(&text, ff) && exit_code == 0)
         exit_code = buildFileToSelf(text, force);
-    }
+
     return exit_code;
 
 error:

+ 0 - 39
src/main_signal.c

@@ -1,39 +0,0 @@
-#include "aFun.h"
-#include "signal.h"
-#include "main.h"
-#include "main_signal.h"
-
-static volatile sig_atomic_t sig = 0;  // SIGINT (Windows & *nix)
-
-static void sigFunc(int signum);
-static void sigFunc(int signum) {
-    if (signum != SIGINT && signum != SIGTERM)
-        return;
-    sig = 1;
-}
-
-bool getSignal(void) {
-    if (sig == 1 || aFunGetSignal(SIGINT) || aFunGetSignal(SIGTERM)) {
-        sig = 0;
-        signal(SIGINT, sigFunc);
-        signal(SIGTERM, sigFunc);
-        return true;
-    }
-    return false;
-}
-
-void signalInit(SignalInfo *si) {
-    writeDebugLog(aFunlangLogger, "aFunlang signal init");
-    sig = 0;
-    si->sig_int = signal(SIGINT, sigFunc);
-    si->sig_term = signal(SIGTERM, sigFunc);
-}
-
-void signalRecover(SignalInfo *si) {
-    writeDebugLog(aFunlangLogger, "aFunlang signal init");
-    sig = 0;
-    if (si->sig_int != SIG_ERR)
-        signal(SIGINT, si->sig_int);
-    if (si->sig_term != SIG_ERR)
-        signal(SIGTERM, si->sig_term);
-}

+ 0 - 15
src/main_signal.h

@@ -1,15 +0,0 @@
-#ifndef AFUN_MAIN_SIGNAL_H
-#define AFUN_MAIN_SIGNAL_H
-#include "main.h"
-
-typedef struct SignalInfo SignalInfo;
-struct SignalInfo {
-    void *sig_int;
-    void *sig_term;
-};
-
-bool getSignal(void);
-void signalInit(SignalInfo *si);
-void signalRecover(SignalInfo *si);
-
-#endif //AFUN_MAIN_SIGNAL_H

+ 7 - 3
src/runtime/aFunlang.c

@@ -36,6 +36,10 @@ void defineRunEnv(aFunRunInfo *run_env) {
     defineRunEnvCore(run_env);
 }
 
+void redefRunEnvSignal(void) {
+    aFunSignalInit(NULL);
+}
+
 /*
  * 函数名: undefRunEnv
  * 目标: 取消运行前的初始哈
@@ -157,14 +161,14 @@ int runCodeFromFileSource(FilePath file, bool save_afb, FilePath save_path, int
  * 函数名: runCodeFromStdin
  * 目标: 运行stdin的程序 (源码形式)
  */
-int runCodeFromStdin(char *name, ParserStdinInterruptFunc *interrupt, af_Environment *env){
-    if (env == NULL || CLEAR_FERROR(stdin) || feof(stdin) || !aFunInit_mark)  // ferror在feof前执行
+int runCodeFromStdin(char *name, af_Environment *env){
+    if (env == NULL || CLEAR_STDIN() || !aFunInit_mark)  // ferror在feof前执行
         return -1;
 
     if (name == NULL)
         name = "sys-stdin.aun";
 
-    af_Parser *parser = makeParserByStdin(interrupt);
+    af_Parser *parser = makeParserByStdin();
     return runCode_(name, parser, 0, NULL, env);
 }
 

+ 1 - 1
src/tool/stdio_.c

@@ -162,7 +162,7 @@ int fgets_stdin(char **dest, int len) {
  *
  * 参考自: https://gist.github.com/SuperH-0630/a4190b89d21c349a8d6882ca71453ae6
  */
-bool checkStdin(void){
+bool checkStdin(void) {
     bool re = false;
 
     int oldf = fcntl(STDIN_FILENO, F_GETFL, 0);