Почему родительский процесс не возвращается в точное место после обработки сигнала?

#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>

sig_atomic_t child_exit_status;

void clean_up_child_process (int signal_number)
{
  /* Clean up the child process.  */
  int status;
  wait (&status);
  /* Store its exit status in a global variable.  */
  child_exit_status = status;
}

int main ()
{
  /* Handle SIGCHLD by calling clean_up_child_process.  */
  struct sigaction sigchld_action;
  memset (&sigchld_action, 0, sizeof (sigchld_action));
  sigchld_action.sa_handler = &clean_up_child_process;
  sigaction (SIGCHLD, &sigchld_action, NULL);

  /* Now do things, including forking a child process.  */
  /* ...  */
  pid_t t = fork();
  if (t!=0) {
      // parent
      sleep(30);    // After handling signal, why does it not continue to sleep 20 (30-10) more seconds?
      printf("Parent exits\n");
  }
  else {
      // child
      sleep(10);
      printf("child exists\n");
  }

  return 0;
}

Результат, который я получил, через 10 секунд и дочерний, и родительский процессы распечатывают свое сообщение, а затем выходят. Я ожидаю, что дочерний процесс сначала распечатает сообщение, затем родительский процесс будет спать еще около 20 секунд, прежде чем распечатать свое сообщение и выйти. Почему родительский процесс не возвращается к «точному местоположению» перед обработкой сигнала, который спит еще 20 секунд? Есть ли способ, которым я могу достичь этого?


person Community    schedule 29.07.2011    source источник
comment
Вы должны не memset и struct sigaction, а заполнить поля (sigemptyset(&sigchld_action.sa_mask) (или sigfillset), sa_flags и одно из sa_handler и sa_sigaction). sigemptyset может не совпадать с memset.   -  person jilles    schedule 30.07.2011


Ответы (2)


sleep(3) не перезапускается в случае сигнала.

Возвращаемое значение: ноль, если запрошенное время истекло, или количество секунд, оставшееся до ожидания, если вызов был прерван обработчиком сигнала.

Поэтому вы должны проверить возвращаемое значение и снова заснуть. Что-то вроде (не проверено):

rc = 30;
while ((rc = sleep(rc)))
    ;
person cnicutar    schedule 29.07.2011

Учтите, что вы можете захотеть прервать операцию блокировки/select()/poll()/sleep(). Один из способов сделать это — послать сигнал, который может привести к выходу текущей функции с кодом EINTR.

Существует флаг SA_RESTART, который вызывает перезапуск некоторых функций при получении сигнала, в основном read() и write(). Поведение других функций зависит от реализации.

person ninjalj    schedule 29.07.2011