Поэкспериментировал и нашел один вариант, который с натяжкой может считаться
решением задачи: обработка юниксовых сигналов.
Если внутри обработчика сигнала случится exception, то результатом будет необработанное исключение, даже если в это время код основной программы находится внутри блока try:
- Код: Выделить всё
{$mode objfpc}
uses baseunix;
procedure catchalarm (signo:integer);cdecl;
begin
writeln ('пойман алярм: ', signo);
// pbyte(nil)^:=0;
end;
procedure proc();
var set1:sigset_t;
act:sigactionrec;
begin
fpsigfillset (set1);
fpsigdelset (set1, SIGALRM);
act.sa_handler := SigActionHandler(@catchalarm);
fpsigaction (SIGALRM, @act, nil);
writeln('Спим до получения SIGALRM');
fpsigsuspend(set1);
writeln('Проснулись после SIGALRM');
end;
begin
writeln('Сигналить с помощью kill -SIGALRM ',fpgetpid());
try
proc()
except
end;
writeln('Завершение работы');
end.
Здесь задаем свой обработчик сигнала SIGALRM и блокируем программу внутри proc() до получения этого сигнала. Если оставить генерацию исключения в комментариях (// pbyte(nil)^:=0;), то программа отработает штатно:
- Код: Выделить всё
Сигналить с помощью kill -SIGALRM 4470
Спим до получения SIGALRM
Затем программа висит во вроде-бы безопасном блоке try, ждет сигнала. В параллельной консоли сигналим, как требует программа:
kill -SIGALRM 4470 (4470 - пример, номер процесса у каждого будет свой и каждый раз разный). Получив сигнал, программа задействует его обработчик:
- Код: Выделить всё
пойман алярм: 14
По окончании размораживает основной код:
- Код: Выделить всё
Проснулись после SIGALRM
и отрабатывает после блока except
- Код: Выделить всё
Завершение работы
Если раскомментируем
pbyte(nil)^:=0;, то получим:
- Код: Выделить всё
Сигналить с помощью kill -SIGALRM 5067
Спим до получения SIGALRM
пойман алярм: 14
Ошибка сегментирования
Ясно видно, что блок except не помог. Скажу больше, даже если обработчик сигнала представить следующим образом:
- Код: Выделить всё
procedure catchalarm (signo:integer);cdecl;
begin
writeln ('пойман алярм: ', signo);
try
pbyte(nil)^:=0;
except
end;
end;
То даже этот блок except не сработает, ошибка сегментирования гарантирована.
К сожалению, эта программа не совсем соответствует условию задачи, т.к. не срабатывает не только ближайший, но и глобальный обработчик исключений. И вместо ожидаемого runtime error 216, получаем сообщение, генерируемое осью