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/ |