OberonCore
https://forum.oberoncore.ru/

HandleTrap обработка ^C
https://forum.oberoncore.ru/viewtopic.php?f=134&t=6960
Страница 1 из 1

Автор:  arisu [ Четверг, 03 Август, 2023 13:00 ]
Заголовок сообщения:  HandleTrap обработка ^C

ещё настойчиво рекомендую в `HandleTrap()` сделать примерно вот так:
Код:
   PROCEDURE GetSigILLVal (pc: ADDRESS): INTEGER;
   VAR err, val: INTEGER;
   BEGIN
      err := 202; val := 0;
      IF platform.p.IsReadable(pc, pc + 4) THEN
         S.GET(pc, val);
         IF val MOD 100H = 8DH THEN   (* lea reg,reg *)
            IF val DIV 100H MOD 100H = 0F0H THEN
               err := val DIV 10000H MOD 100H   (* trap *)
            ELSIF val DIV 1000H MOD 10H = 0EH THEN
               err := 128 + val DIV 100H MOD 10H   (* run time error *)
            END
         END
      END;
      RETURN err
   END GetSigILLVal;

   (* check if we are inside a Kernel/HostKernel, or OS libraries *)
   PROCEDURE CheckPC (pc: ADDRESS): INTEGER;
   VAR
      res: INTEGER;
      mod: Kernel.Module;
   BEGIN
      mod := Kernel.modList;
      WHILE (mod # NIL) & ((pc < mod.code) OR (pc >= mod.code + mod.csize)) DO
         mod := mod.next
      END;
      IF mod # NIL THEN
         IF (mod.name = "Kernel") OR (mod.name = "HostKernel") THEN res := pcInKernel
         ELSE res := pcInModule
         END
      ELSE pc := pcInOSLibs
      END;
      RETURN res
   END CheckPC;

   PROCEDURE [cdecl] HandleTrap (sig: INTEGER; siginfo: Libc.Ptrsiginfo_t; context: Libc.Ptrucontext_t);
   VAR
      inSignalStack: BOOLEAN;
      oldpc, oldfp: ADDRESS;
      pcpos: INTEGER;
   BEGIN
      pcpos := CheckPC(context.uc_mcontext.gregs[14]); (* pc *)
      IF sig = Libc.SIGINT THEN
         (* ignore Ctrl+C if we are in some unsafe to break code *)
         IF pcpos # pcInModule THEN
            RETURN
         END;
      ELSE
         (* if we trapped inside a kernel, panic and exit, this should not happen!
            if we will not panic, recursive traps may occur.
            FIXME! *)
         IF pcpos = pcInKernel THEN
            (* FIXME: this is dangerous; i should find another way to allow asserts/halts in kernel! *)
            CASE sig OF
            | Libc.SIGILL:   (* this is either HALT or runtime error *)
               pcpos := GetSigILLVal(context.uc_mcontext.gregs[14]);
               IF pcpos >= 128 THEN   (* runtime error *)
                  log.String("FATAL: runtime error"):Int(pcpos - 128):
                     String(" in Kernel, PC="):Adr(oldpc):String(". Aborting immediately."):Ln;
                  Libc.exit(2)
               END
            | Libc.SIGSEGV:
               log.String("FATAL: segmentation fault in Kernel, PC="):Adr(oldpc):String(". Aborting immediately."):Ln;
               Libc.exit(2)
            ELSE END CASE
         END
      END;

      sp := context.uc_mcontext.gregs[7]; (* stack pointer *)
      fp := context.uc_mcontext.gregs[6]; (* frame pointer *)
      …и так далее…

ну, вы поняли идею. делать ^C в ядре нельзя, потому что мы можем быть посреди процесса сборки мусора, и в итоге память окажется порубаной в лапшу. виндоядро имеет такую охрану, а позикс-ядра нет, и в итоге в позиксах ^C — русская рулетка.

в общем, сделайте что-то по мотивам этого кода у себя.

Автор:  Иван Денисов [ Вторник, 08 Август, 2023 00:45 ]
Заголовок сообщения:  Re: BlackBox 2.0

arisu писал(а):
ещё настойчиво рекомендую в `HandleTrap()` сделать примерно вот так:

Решение надо будет как-то дорабатывать, а то в целом Блэкбокс перестаёт по Ctrl+C завершаться. Наверное он большую часть времени крутится в ядре. Надо тогда по Ctrl+C устанавливать какой-то флаг, чтобы как он из ядра выходил, тогда и останавливал выполнение.

Автор:  arisu [ Вторник, 08 Август, 2023 12:39 ]
Заголовок сообщения:  Re: BlackBox 2.0

Иван Денисов писал(а):
arisu писал(а):
ещё настойчиво рекомендую в `HandleTrap()` сделать примерно вот так:

Решение надо будет как-то дорабатывать, а то в целом Блэкбокс перестаёт по Ctrl+C завершаться.
а он и не должен.
Иван Денисов писал(а):
Наверное он большую часть времени крутится в ядре.
он в основном сидит в готэка, ожидает события. технически кидать сигналы прерываний когда мы в системных библиотеках — плохо, поэтому и не кидаем. Ctrl+C — так же, как Ctrl+Break в оригинале — предназначена для того, чтобы прервать зациклившийся код на компонентном паскале. именно так оно в виндовом оригинале и работало. то, что до правок Ctrl+C работало иначе — это был баг.

Иван Денисов писал(а):
Надо тогда по Ctrl+C устанавливать какой-то флаг, чтобы как он из ядра выходил, тогда и останавливал выполнение.
ну, есть нюанс: если запустить тот же тест выделений памяти — да, прервать сложно: тут он как раз в основном в ядре и крутится. я у себя сделал счётчик проигнорированых прерываний, и в `Kernel.Collect()` (и `FastCollect()`) его проверяю. если больше трёх — то просто делаю `HALT()` там.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/