Системное программирование в UNIX средствами Free Pascal

Нормальное и аварийное завершение


Получение большинства сигналов приводит к нормальному завершению

(normal termination)

процесса. Действие сигнала при этом похоже на неожиданный вызов процессом функции _exit. Статус завершения, возвращаемый при этом родительскому процессу, сообщит о причине завершения дочернего процесса. В файле stdio определены макросы, которые позволяют родительскому процессу определить причину завершения дочернего процесса (получение сигнала и, собственно, значение сигнала. Следующий фрагмент программы демонстрирует родительский процесс, проверяющий причину завершения дочернего процесса и выводящий соответствующее сообщение:

uses stdio;

.

.

pid:=wait(@status);

if pid=-1 then

begin

  perror('ошибка вызова wait');

  halt(1);

end;

(* Проверка нормального завершения дочернего процесса *)



if WIFEXITED(status) then

begin

  exit_status := WEXITSTATUS(status);

  writeln('Статус завершения ', pid, ' был ', exit_status);

end;

(* Проверка, получил ли дочерний процесс сигнал *)

if WIFSIGNALED(status) then

begin

  sig_no := WTERMSIG(status);

  writeln('Сигнал номер ', sig_no, ' завершил процесс ', pid);

end;

(* Проверка остановки дочернего процесса *)

if WIFSTOPPED(status) then

begin

  sig_no := WSTOPSIG(status);

  writeln('Сигнал номер ', sig_no, ' остановил процесс ', pid);

end;

Как уже упоминалось, сигналы SIGABRT, SIGBUS, SIGSEGV, SIGQUIT, SIGILL, SIGTRAP, SIGSYS, SIGXCPU, SIGXFSZ и SIGFPE приводят к аварийному завершению и обычно сопровождаются сбросом образа памяти на диск. Образ памяти процесса записывается в файл с именем core в текущем рабочем каталоге процесса (термин core, или сердечник, напоминает о временах, когда оперативная память состояла из матриц ферритовых сердечников). Файл core будет содержать значения всех переменных программы, регистров процессора и необходимую управляющую информацию ядра на момент завершения программы. Статус завершения процесса после аварийного завершения будет тем же, каким он был бы в случае нормального завершения из-за этого сигнала, только в нем будет дополнительно выставлен седьмой бит младшего байта. В большинстве современных систем UNIX




определен макрос WCOREDUMP, который возвращает истинное или ложное значение в зависимости от установки этого бита в своем аргументе. Тем не менее следует учесть, что макрос WCOREDUMP не определен спецификацией XSI. С применением этого макроса предыдущий пример можно переписать так:

(* Проверка, получил ли дочерний процесс сигнал *)

if WIFSIGNALED(status) then

begin

  sig_no := WTERMSIG(status);

  writeln('Сигнал номер ', sig_no, ' завершил процесс ', pid);

  if WCOREDUMP(status) then

    writeln('... создан файл дампа памяти');

end;

Формат файла core известен отладчикам UNIX, и этот файл можно использовать для изучения состояния процесса в момент сброса образа памяти. Этим можно воспользоваться для определения точки, в которой возникает проблема.

Стоит также упомянуть функцию abort, которая не имеет аргументов:

abort;

Эта функция посылает вызвавшему ее процессу сигнал SIGABRT, вызывая его аварийное завершение, то есть сброс образа памяти. Процедура

abort полезна в качестве средства отладки, так как позволяет процессу записать свое текущее состояние, если что-то происходит не так. Она также иллюстрирует тот факт, что процесс может послать сигнал самому себе.


Содержание раздела