LINUX.ORG.RU

Некорректная работа учебной программы обработки сигналов

 ,


0

1

Добрый вечер , увжаемые форумчане! Хочу попросить знающих людей посмотреть мой код и объяснить несколько вещей по нему .Прошу сильно не пинать - программа это задние по предмету в инсте, под позикс впервый раз проги пишу., писал все по не самому лучшему рукрвдоству, данному преподавтелем. Компилирую в gcc под Fedora 17.

Собственно, интересуют 2 вещи 1)Почему в дочернем процессе Childprocess после подключения обработчика handler_FPE и первого деления m/e (e=0) происходит зацикливание обработчика.? 2) вопросы по обработчику handler_CHLD 2.1 Почему если убрать комментарии с if (нужны по условию задачи), то обработчик будет зависать при исполнении? 2.2 По условию задачи обраюботчик должен заносить в струтуру все изменеия состояния дочернего процесса (при приостанвке , передаче работы основному процессу и при выходе). Сейчас туда заносится информация только один раз при завершении дочернего процесса. Как можно реализовать требуемй функционал ?

Вот код (на комментарии не обращайте внимания? в цедом они правильные, но я их пока для себя писал, часто копипастил и не все поправлял) :

#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <errno.h>

//Глобальные переменные
int a,b,c,d,g,i,n;
int k=0;
  //Переменная для идентификатора процесса
int pid_child;

siginfo_t siginfo;

struct StructChild
{
  int pid;
  int status;
  int code;
};
 
struct StructChild StrChld[4];

//Обработчик сигнала 1
void handler1(int signo)
{  
   printf("\nhandler1\n");
  //Присваиваем значение 1 переменной g при поступлении сигнла SIGUSR1
  if (signo==SIGUSR1)
   {
    g = 1;
    printf("\nVariable g - %d\n", g); 
   }  
 //Присваиваем значение 2 переменной g при поступлении сигнла SIGUSR2
   if (signo==SIGUSR2)
    {
     g = 2;
     printf("\nVariable g - %d\n", g );
    }
}

//Обработчик сигнала SIGUSR1
void handler_SIGUSR1()
{
  printf("\nhandler_SIGUSR1\n");
  //Увеличиваем значение переменной a и выводим для проверки
  a += 1;
  printf("\nVariable a - %d\n", a);
 //Увеличиваем значение переменной b и выводом для проверки
  b += 1;
  printf("\nVariable b - %d\n", b );
}

//Обработчик сигнала SIGUSR2
void handler_SIGUSR2()
{ 
  printf("\nhandler_SIGUSR2\n");
  //Увеличиваем значение переменной a и выводим для проверки
  a += 1;
  printf("\nVariable a - %d\n", a);
 //Увеличиваем значение переменной b и выводом для проверки
  c += 1;
  printf("\nVariable c - %d\n", c );
}

//Обработчик сигнала SIGFPE
void handler_SIGFPE()
{
  //Увеличиваем значение переменной a и выводим для проверки
  a += 1;
  printf("\nVariable a - %d\n", a);
 //Увеличиваем значение переменной b и выводом для проверки
  d += 1;
  printf("\nVariable d - %d\n", d );
}

//Обработчик сигнала SIGCHLD
void handler_CHLD()
{
  printf("\nhandler_CHLD\n");
  StrChld[k].pid=siginfo.si_pid;
  StrChld[k].status=siginfo.si_status;
  StrChld[k].code=siginfo.si_code; 
  k+=1;
  if ((siginfo.si_code==CLD_EXITED) || (siginfo.si_code==CLD_DUMPED) ||(siginfo.si_code==CLD_KILLED)) 
 {
  if (siginfo.si_pid==pid_child)
 {
    //значение переменной i и выводим для проверки
    i = 1;
    printf("\nVariable i - %d\n", i);
  }
 }
  
}


//Дочерний процесс
void childProcess()
{
  //Запоминаем текущий приоритет
  struct sched_param sch_pCHLD;
  int CurrentChildPrioritet=sched_getparam(getpid(),&sch_pCHLD);
  //Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction sa1;
  
   //Указываем обработчик сигнала 
  sa1.sa_handler = handler1;

  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGUSR1, &sa1, 0); 
  sigaction(SIGUSR2, &sa1, 0); 
 //Объявляем набор сигналов set1
  sigset_t set1;
 //Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigfillset(&set1);
//Исключаем сигналы SIGUSR1 , SIGUSR2 и SIGFPE из этого набора
  sigdelset(&set1, SIGUSR1);
  sigdelset(&set1, SIGUSR2);
  sigdelset(&set1, SIGFPE);
//Проверяем наличие сигналов SIGUSR1 , SIGUSR2 и SIGFPE в наборе
  if (sigismember(&set1, SIGUSR1)==1)
   {
     printf("\nError! Signal SIGUSR1 is in set1!\n");
     
   }
  if (sigismember(&set1, SIGUSR2)==1)
   {
     printf("\nError! Signal SIGUSR2 is in set1!\n");
     
   }
  if (sigismember(&set1, SIGFPE)==1)
   {
     printf("\nError! Signal SIGFPE is in set1!\n");
     
   }
 //Устанавливаем текущим набор сигналов set1
  sigprocmask(SIG_SETMASK,&set1,0);
 //Проверяем правильность установленной маски  
  if(sigprocmask(SIG_SETMASK,0,&set1)==1)
    {
     printf("\nError! Set1 is not in current mask!\n");
     
    }
 //Обнуляем g 
    g=0;
 //Приостанавливаем работу tsk1
   sigsuspend(&set1);
 //Проверяем значение переменной g = 1 после выхода из приостанова  
   if (g!=1)
    {
      printf("\nError! Variable g!=1\n");
      
    }
 //Вновь приостанавливаем работу tsk1
    sigsuspend(&set1);
 //Проверяем значение переменной g = 2 после выхода из приостанова  
    if (g!=2)
     {
       printf("\nError! Variable g!=1\n");
       
     }
  //Объявляем набор сигналов set2
  sigset_t set2;
 //Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigfillset(&set2);

//Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saUSR1;
  
   //Указываем обработчик сигнала 
  saUSR1.sa_handler = handler_SIGUSR1;
  saUSR1.sa_flags = 0;
  saUSR1.sa_mask = set2;
  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGUSR1, &saUSR1, 0); 


  //Объявляем набор сигналов set3
  sigset_t set3;
  //Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigemptyset(&set3);
  //Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saUSR2;
  
   //Указываем обработчик сигнала 
  saUSR2.sa_handler = handler_SIGUSR2;
  saUSR2.sa_flags = 0;
  saUSR2.sa_mask = set3;
  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGUSR2, &saUSR2, 0); 
 
  //Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saFPE;
  
   //Указываем обработчик сигнала 
  saFPE.sa_handler = handler_SIGFPE;
  saFPE.sa_flags = 0;
  saFPE.sa_mask = set2;
  //Присваиваем обработчик сигналам SIGUSR1 и SIGUSR2
  sigaction(SIGFPE,&saFPE, 0);
  //Обнуляем переменные 
   a=0;
   b=0;
   c=0;
   d=0;
  //Запускаем цикл тестирования перемнной а на нулевое значение
  for(;;)
  {
    if (a!=0)
    {break;}
   }
  //Уменьшаем значение переменной а на 1
   a-=1;
 //Проверяем значение переменной b = 1 
   if (b!=1)
    {
      printf("\nError! Variable b!=1\n");
          }

  struct timespec req;
  struct timespec rem;
 
  // 2 секунды , 300 наносекунд
  req.tv_sec = 2;
  req.tv_nsec = 300;

  //nanosleep(&req,&rem);

 //Запускаем цикл тестирования перемнной а на нулевое значение
   for(;;)
   {
    if (a!=0)
    {break;}
   }
//Уменьшаем значение переменной а на 1
   a-=1;
//Проверяем значение переменной c = 1   
   if (c!=1)
    {
      printf("\nError! Variable с!=1\n");
      
    }
 //Модифицируем набор сигналов 1, добавляем в него сигнал SIGUSR1 (он будет заблокирован)
   sigaddset(&set1, SIGUSR1);
 
//Проверяем наличие сигнала SIGUSR1  в наборе сигналов 1
  if (sigismember(&set1, SIGUSR1)!=1)
   {
     printf("\nError! Signal SIGUSR1 is not in set1!\n");
     
   }

//Объявляем наборы сигналов set4,oldset
  sigset_t set4;
  sigset_t oldset;
  
//Устанавливаем текущим набор сигналов set4 и запоминаем текущий набор в oldset
  sigprocmask(SIG_SETMASK,&set4,&oldset);

 //Проверяем правильность установленной маски  
  //if(oldset!=set1)
   // {
   //  printf("\nError! Oldset is not equal to Set1!\n");
     
  //  }

  sigprocmask(SIG_BLOCK,&set1,0);
//Запускаем цикл тестирования перемнной а на нулевое значение
  for(;;)
  {
    if (a!=0)
   { break;}
   }
//Уменьшаем значение переменной а на 1
   a-=1;
 //Проверяем значение переменной b = 1  
   if (b!=1)
    {
      printf("\nError! Variable b!=1\n");
      
    }
//Проверяем значение переменной c = 2  
   if (c!=2)
    {
      printf("\nError! Variable с!=2\n");
      
    }
//Присоединяем все сигналы, ожилающие в заблокированном сотсняии набору 4
    sigpending(&set4);

//Проверяем наличие сигнала в наборе 4
  if (sigismember(&set4, SIGUSR1)!=1)
   {
     printf("\nError! Signal SIGUSR1 is not in set4!\4");
     
   }
//Устанавливаем текущим набор сигналов set4 и разблокируем в нем сигналы
  sigprocmask(SIG_UNBLOCK,&set4,0);
//Запускаем цикл тестирования перемнной а на нулевое значение
  for(;;)
  {
    if (a!=0)
     {break;}
   }
//Уменьшаем значение переменной а на 1
   a-=1;
//Проверяем значение переменной b = 2
   if (b!=2)
    {
      printf("\nError! Variable b!=2\n");
      
    }
//Проверяем значение переменной c = 2  
   if (c!=2)
    {
      printf("\nError! Variable с!=2\n");
     
    }
//Объявляем набор сигналов set5
  sigset_t set5;
//Инициируем этот набор,включая внего все сигналы в системе (все сигналы блокируются)
  sigemptyset(&set5);
  //Добавляем сигналы SIGUSR1 и SIGUSR2 в этот набор
  sigaddset(&set5, SIGUSR1);
  sigaddset(&set5, SIGUSR2);
//Устанавливаем текущим набор сигналов set5 и запоминаем текущий набор в oldset
  sigprocmask(SIG_BLOCK,&set5,0);
//Проверяем наличие сигналов SIGUSR1 , SIGUSR2  в наборе
  if (sigismember(&set5, SIGUSR1)!=1)
   {
     printf("\nError! Signal SIGUSR1 is not in set5!\n");
     
   }
  if (sigismember(&set5, SIGUSR2)!=1)
   {
     printf("\nError! Signal SIGUSR2 is not in set5!\n");
     
   }
//

  nanosleep(&req,&rem);
//Определяем перменные м и е
  int m,e;
  m=1;
  e=0;
  //m=m/e;

 //Проверяем значение переменной a = 1  
   if (a!=1)
    {
      printf("\nError! Variable a!=1\n");
      
    }
//Проверяем значение переменной d = 1 
   if (d!=1)
    {
      printf("\nError! Variable d!=1\n");
      
    }
  //nanosleep(&req,&rem);
//Объявляем структуру в которой хранится информация об обработчике сигналов
  struct sigaction saOLD;
//Присваиваем  игноррование в качестве обработчика сигналу SIGFPE
  saFPE.sa_handler=SIG_IGN;
  sigaction(SIGFPE, &saFPE, &saOLD); 
//Уменьшаем значение а на 1
  a-=1;
//Опять делим е на м чтобы получить сигнал SIGFPE
  m=1;
  m=m/e;
 //Проверяем значение переменной a = 0 
   if (a!=0)
    {
      printf("\nError! Variable a!=0\n");
      
    }

//Определяем обработчик сигнала , имеющийся в системе по умолчанию сигналу SIGFPE

  saFPE.sa_handler=SIG_DFL;
  sigaction(SIGFPE,&saFPE, 0);
//Опять делим е на м
  e=0;
  m=1;
  m=m/e;
 kill(0,SIGCHLD);
   
}


void main()
{

  // Объявляем структуру которая хранит параметры приоритетов
  struct sched_param sch_p;

  // Запоминаем приоритет и политику планировщика
  int currentPriority = sched_getparam(getpid(),&sch_p);
  int currentPolicy = sched_getscheduler(getpid());
  

  //Устанавливаем политику FIFO
  sched_setscheduler(getpid(), SCHED_FIFO, &sch_p);
 
  
//Объявляем обработчки сигнала SIGCHLD с установкой флагов

  struct sigaction saCHLD;
  saCHLD.sa_handler = handler_CHLD;
  saCHLD.sa_flags = SA_SIGINFO;
  sigaction(SIGCHLD, &saCHLD, 0); 

//

    int n = 3;
//Создаем структуры которые хранят время для nanosleep
  struct timespec req;
  struct timespec rem;

  // 2 секунды , 300 наносекунд
  req.tv_sec = 2;
  req.tv_nsec = 300;
 

  // Создаем дочерний процесс, если вернулся ноль, то мы в дочернем процессе и идем в функцию childProcess
  if ((pid_child= fork()) == 0)
     childProcess();

  //А в это время основной процесс приостанавливается на 2 секунды 100 наносекунд
  nanosleep(&req, &rem);


  while (n>0)
    {
      kill(pid_child,SIGUSR1);
      if(n!=2)
      {
       nanosleep(&req,&rem);
      }
      kill(pid_child,SIGUSR2);
      nanosleep(&req,&rem);
      n-=1;
     }


//Запускаем цикл тестирования перемнной i на нулевое значение
  for(;;)
  {
    if (i!=0)
    {break;}
   }

 printf("\nVector StrChld in %i elements:\n",k);
 int s;
 for (s=0;s<k;s++)
 {
  printf("\npid=%i , status=%i , code=%i\n",StrChld[s].pid,StrChld[s].status,StrChld[s].code);
  }
 }


Последнее исправление: Bennett (всего исправлений: 1)

LORCODE для слабаков?

erfea ★★★★★
()
Ответ на: комментарий от v9lij

Понимаю, код плохо читабелен.При добавлении в редакторе он нормально отображался, но при нажатии отправить все строки стали как сейчас Не подскажешь, как сделать, чтобы он норально отображлся?

Bennett
() автор топика

Лучше разбивайте код на маленькие примеры и задавайте вопрос по каждому отдельно.

1)Почему в дочернем процессе Childprocess после подключения обработчика handler_FPE и первого деления m/e (e=0) происходит зацикливание обработчика

После завершения обработчика sigfpe следующей выполенной инструкцией будет та, в которая привела к ошибке, а не следующая.
Ответ легко гуглится: http://technopark02.blogspot.ru/2005/10/handling-sigfpe.html

gv
()
Ответ на: комментарий от gv

Спасибо большое за помощь! С SIGFPE поправил, теперь все ок. Я просто не очень хорошо гуглую по теме на Инглише.. А про комментарии я писал быстро тогда и немного не точно описал , а потом при редактировании здесь на форуме изменил немного код Имелось ввиду вот что : if ((siginfo.si_code==CLD_EXITED) || (siginfo.si_code==CLD_DUMPED) ||(siginfo.si_code==CLD_KILLED)) { if (siginfo.si_pid==pid_child)

С этими ифами (они были закомментирвоаны просто в изначальном варианте кода, что я выкладывал) программа зависает.и яне пойму по чему.А по условию задачи эта ппроверка нужна. Без них все рабтает и вмассиве стуртур формируетя одна сруктра (а по условию должно бытькак я в 2.2 описал)..

Bennett
() автор топика
Ответ на: комментарий от Bennett

В каком месте зависает?

Попробуйте объявить i как volatile.
Попробуйте убрать printf из обработчика.

Если не поможет - выкладывайте тогда минимальный пример, который не работает, в этот вряд ли люди вчитываться будут.

gv
()

C ифами вобработчике разобрался. Осталочь решить вопрос с вызовом обработчика сигнала SIGCHLD не только в конце работы, дочернего процесса, но и при его присотановке и предаче управления родлительскому процессу. Внятного объяснения работы SIGCHLD и сосбенностей его вызовов я ,к сожалению ,не нашел...

Bennett
() автор топика
Ответ на: комментарий от Bennett

А что такое приостановка и что такое предача управления родительскому процессу?

Почитайте man ptrace, может это то, что вам нужно.

gv
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.