Есть подсистема для локального тестирования олимпиадных (и прочих учебных) задач для школ. Пишешь решение, тыкаешь коммандер, решение прогоняется на наборе тестовых входных-выходных файлов. Это работает.

Задача такая. Если программа думает более 5 секунд, надо вежливо попросить её на выход и сообщить, что вышло время ожидания на тесте таком-то.
Как сделать таймер и зарядить его на 5 секунд я подсмотрел в DevProfiler. Это работает.Как снять задачу?HALT или ASSERT в обработчике таймера не прокатят, поскольку обработчик выполняется (насколько я понял) в контексте другого потока.

Я подумал сделать по аналогии с Ctrl+Break. Там основной поток ставится на паузу, после чего в его контексте устанавливается флаг трэпа:
## Код:
```
res := KERNEL32.SuspendThread(main);
      context.flags := {0, 16};
      res := KERNEL32.GetThreadContext(main, context);
      INCL(SYSTEM.VAL(SET, context.pf), 8);   (* set trap flag *)
      res := KERNEL32.SetThreadContext(main, context);
      res := KERNEL32.ResumeThread(main)
```

Если бы это удалось, то достаточно было бы проигнорировать последующий трэп (обработка трэпов при работе тестируемой задачи тоже уже реализована). Проблема в том, что Kernel.TryHandler игнорирует создаваемый таким образом трэп EXCEPTION_SINGLE_STEP, если переменная Kernel.interrupted = FALSE (устанавливается в TRUE только в обработчике Ctrl+Break). Эта переменная не экспортирована.

Как бы нам в такой ситуации поступить? Экспортировать Kernel.interrupted не хочется. Ещё более не хочется видеть сообщение "keyboard interrupt". Возможно ли возбудить исключение с кодом 128, которое отработает без шума и пыли? Может быть кто-то может порекомендовать какое-нибудь шаманство с Context.ip (instruction pointer)? Например, прыжок в процедуру/на инструкцию HALT(128), но это я корректно сделать не умею.

Какие мысли есть по этому поводу?