Russian Qt Forum
Август 17, 2018, 09:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Работа с сигналами  (Прочитано 736 раз)
demaker
Птица говорун
*****
Offline Offline

Сообщений: 924


Просмотр профиля
« : Май 07, 2018, 13:00 »

Написал простую программку для исследования работы сигналов в ОС Линукс

Вот код программы:

main.cpp
Код
C++ (Qt)
#include "mainwindow.h"
#include <signal.h>
 
#include <QApplication>
 
static void sighandler(int sig)
{
   switch(sig){
 
   case SIGCHLD:
       printf("catch signal handler signal number = %d\n ",sig);
       printf("discribe signal:  %s\n",sys_siglist[sig]);
       wait(0);
       return;
 
   case SIGUSR1:
       printf("catch SIGUSR1 handler signal number = %d\n ",sig);
       printf("discribe signal:  %s\n",sys_siglist[sig]);
       return;
 
   case SIGUSR2:
       printf("catch SIGUSR2 handler signal number = %d\n ",sig);
       printf("discribe signal:  %s\n",sys_siglist[sig]);
       return;
 
   default:
       return;
   }
}
 
int main(int argc, char *argv[])
{
   //подключение обработки сигнала SIGCHLD
   if(signal(SIGCHLD,sighandler) == SIG_ERR){
       fprintf(stderr,"ERROR SIGKILL\n");
       exit(EXIT_FAILURE);
   }
 
   //подключение обработки сигнала SIGUSR1
   if(signal(SIGUSR1,sighandler) == SIG_ERR){
       fprintf(stderr,"ERROR SIGKILL\n");
       exit(EXIT_FAILURE);
   }
 
   //подключение обработки сигнала SIGUSR2
   if(signal(SIGUSR2,sighandler) == SIG_ERR){
       fprintf(stderr,"ERROR SIGKILL\n");
       exit(EXIT_FAILURE);
   }
 
 
   int var = 0;
   int a_exec = 0;
 
   pid_t pid = fork();
   if(pid > 0){
       //var = 1;
       QApplication a(argc, argv);
       MainWindow w;
       w.setWindowTitle(QString("parent process pid = %1").arg(getpid()));
       w.show();
       a_exec = a.exec();
   }
   else{
       var = 2;
       QApplication a(argc, argv);
       MainWindow w;
       w.setWindowTitle(QString("child process pid = %1").arg(getpid()));
       w.show();
       a_exec =  a.exec();
   }
 
   qDebug()<<"var = "<<var;
   qDebug()<<"a_exec = "<<a_exec;
 
   return a_exec;
}
 

mainwindow.cpp
Код
C++ (Qt)
 
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
 
   connect(ui->pbCreate,   SIGNAL(clicked()),this,SLOT(clickedCreate()));
   connect(ui->pbKill,     SIGNAL(clicked()),this,SLOT(clickedKill()));
 
   thread = new Thread;
   connect(thread,SIGNAL(sg_child_pid(int))    ,this,SLOT(setTextChildPID(int)));
   connect(thread,SIGNAL(sg_parent_pid(int))   ,this,SLOT(setTextParentPID(int)));
   connect(thread,SIGNAL(fin())                ,this,SLOT(finishedThread()));
   thread->set_active_thread(true);
   thread->start();
}
 
MainWindow::~MainWindow()
{
   delete ui;
}
 
void MainWindow::closeEvent(QCloseEvent * event)
{
   thread->set_active_thread(false);
   thread->quit();
   thread->wait();
   delete thread;
   thread = NULL;
 
   QMainWindow::closeEvent(event);
}
 
void MainWindow::clickedCreate()
{
   if(thread){
       if(!(thread->create_process()))
           thread->set_create_process(true);
   }
}
 
void MainWindow::clickedKill()
{
   if(thread){
       QString str = ui->lePID->text();
       if(!str.isEmpty()){
           pid_t pid = (pid_t)(str.toInt());
           if(!(thread->kill_process(pid))){
               if(!listPID.isEmpty()){
                   listPID.removeOne((int)pid);
               }
               else{
                   qDebug()<<"LIST PID IS EMPTY!";
               }
           }
           else{
               qDebug()<<"CAN NOT DO KILL!";
           }
       }
       else{
           qDebug()<<"ENTER PID NUMBER!";
       }
   }
}
 
void MainWindow::setTextChildPID(int pid)
{
   qDebug()<<__FUNCTION__;
 
   ui->leChildPID->setText(QString("%1").arg(pid));
   listPID.append(pid);
}
 
void MainWindow::setTextParentPID(int pid)
{
   qDebug()<<__FUNCTION__;
 
   ui->leParentPID->setText(QString("%1").arg(pid));
}
 
void MainWindow::finishedThread()
{
   qDebug()<<__FUNCTION__;
}
 

thread.cpp
Код
C++ (Qt)
Thread::Thread(QObject * parent) : QThread(parent)
{
   m_create_process = false;
   m_active_thread = false;
}
 
Thread::~Thread()
{
}
 
bool Thread::active_thread()
{
   bool active;
   mutex_active_thread.lock();
   active = m_active_thread;
   mutex_active_thread.unlock();
   return active;
}
 
void Thread::set_active_thread(bool active)
{
   mutex_active_thread.lock();
   m_active_thread = active;
   mutex_active_thread.unlock();
}
 
void Thread::set_create_process(bool create)
{
   mutex_create_process.lock();
   m_create_process = create;
   mutex_create_process.unlock();
}
 
bool Thread::create_process()
{
   bool create;
   mutex_create_process.lock();
   create = m_create_process;
   mutex_create_process.unlock();
   return create;
}
 
bool Thread::kill_process(pid_t pid)
{
   return kill(pid,SIGKILL);
}
 
void Thread::run()
{
   raise(SIGUSR1);
 
   while(active_thread())//for(;;)
   {
       msleep(5);
       //проверяем флаг на создание нового процесса
       if(create_process()){
       //сбрасываем флаг
           m_create_process = false;
 
           pid_t pid = fork();
           if(pid > 0){    //_____родительский процесс_____
               qDebug()<<"_____PARENT_PROCESS_____";
 
               pid_t childprocess_id = pid;
               pid_t parentprocess_id = getpid();
 
               emit sg_parent_pid((int)(parentprocess_id));
               emit sg_child_pid((int)(childprocess_id));
           }
           else{        
 
               pid_t process_id = getpid();
               qDebug()<<"process_id = "<<process_id;
 
               pid_t parentprocess_id = getppid();
               qDebug()<<"parentprocess_id = "<<parentprocess_id;
 
               //высылаем сигнал родительскому процессу
               kill(parentprocess_id,SIGUSR2);
 
                   QFile file("data.txt");
                   if(file.open(QFile::ReadWrite/*|QFile::Append*/)){
                       file.seek(0);
                       QString str = QString("pid = %1 time = %2:%3:%4:%5\n")
                               .arg(process_id)
                               .arg((QTime::currentTime()).hour())
                               .arg((QTime::currentTime()).minute())
                               .arg((QTime::currentTime()).second())
                               .arg((QTime::currentTime()).msec());
 
                       file.write(str.toLatin1().data(),str.size());
                   }
                   file.close();
 
           }
       }
   }
 
   printf("printf out of thread\n");
   qDebug()<<"qDebug() out of thread";
 
   emit fin();
 

В начале создаются два окна - одно в родительском процессе, одно в дочренем.

В конструкторе MainWindow создается поток, в теле которого может создаваться дочерний
процесс, в котором происходит запись в файл.

Так же мы можем по нажатию кнопки создать еще один дочерний процесс в котором происходит постоянная запись в файл.  

Есть обработчик сигналов, который обрабатывает сигналы SIGCHLD, SIGUSR1,SIGUSR2.
Cоответственно номер SIGCHLD = 17
                              номер SIGUSR1 = 10
                              номер SIGUSR2 = 12

При запуске исполняемого файла из консоли, почему-то сначала появяляется только окно
дочернего процесса и в консоль выводится

Код:
catch signal handler signal number = 17
 discribe signal:  Child exited
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1
catch signal handler signal number = 17
 discribe signal:  Child exited

Такое впечатление что были убиты какие-то дочерние процессы, хотя ничего такого не происходило.

Если же запускать программу из-под креатора то все норм, в консоль креатора ничего такого не
выводится и видно два окна(созданное в родительском и дочернем процессах)

Правильно ли я понимаю, что обработчик сигналов sighandler(int sig) начинает работу после завершения QApplication::exec()

« Последнее редактирование: Май 07, 2018, 14:08 от demaker » Записан
qate
Гипер активный житель
*****
Offline Offline

Сообщений: 887


Просмотр профиля
« Ответ #1 : Май 07, 2018, 14:58 »

все подробно расписал, а проект не приложил на посмотреть, не копипастить же
гдето в статье https://www.macieira.org/blog/2012/07/forkfd-part-4-proposed-solutions/ были упоминания о сигналах, но может и не связано

исследование ради какой цели делается ?
« Последнее редактирование: Май 07, 2018, 15:00 от qate » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 924


Просмотр профиля
« Ответ #2 : Май 07, 2018, 15:08 »

все подробно расписал, а проект не приложил на посмотреть, не копипастить же
гдето в статье https://www.macieira.org/blog/2012/07/forkfd-part-4-proposed-solutions/ были упоминания о сигналах, но может и не связано

исследование ради какой цели делается ?


Исследования делаются для себя, чтобы понимать как правильно работать Улыбающийся
Записан
qate
Гипер активный житель
*****
Offline Offline

Сообщений: 887


Просмотр профиля
« Ответ #3 : Май 07, 2018, 16:05 »

при запуске в консоли два окна и вывод:
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1

какой дистр ?
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 924


Просмотр профиля
« Ответ #4 : Май 07, 2018, 19:58 »

при запуске в консоли два окна и вывод:
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1

какой дистр ?

xubuntu

А обработчик сигналов сообщения выдае при обработке SIGCHLD, когда процессы
убиваешь???
« Последнее редактирование: Май 07, 2018, 20:15 от demaker » Записан
qate
Гипер активный житель
*****
Offline Offline

Сообщений: 887


Просмотр профиля
« Ответ #5 : Май 07, 2018, 20:23 »

Код:
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1






_____PARENT_PROCESS_____
_____CHILD_PROCESS_____
process_id =  16670
parentprocess_id =  16660
catch SIGUSR2 handler signal number = 12
 discribe signal:  User defined signal 2
setTextParentPID
setTextChildPID



catch signal handler signal number = 17
 discribe signal:  Child exited


какая xubuntu и версия qt ?
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 924


Просмотр профиля
« Ответ #6 : Май 08, 2018, 09:54 »

какая xubuntu и версия qt ?


Код:
Distributor ID: Ubuntu
Description: Ubuntu 16.04.1 LTS
Release: 16.04
Codename: xenial
root@evgen-N100SP:/home/evgen# uname -r
4.4.0-112-generic

Linux evgen-N100SP 4.4.0-112-generic #135-Ubuntu SMP Fri Jan 19 11:48:36 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux


Код:
Based on Qt 5.7.1 (GCC 4.9.1 20140922 (Red Hat 4.9.1-10), 64 bit)
« Последнее редактирование: Май 08, 2018, 09:58 от demaker » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 924


Просмотр профиля
« Ответ #7 : Май 08, 2018, 10:00 »

Код:
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1
catch SIGUSR1 handler signal number = 10
 discribe signal:  User defined signal 1






_____PARENT_PROCESS_____
_____CHILD_PROCESS_____
process_id =  16670
parentprocess_id =  16660
catch SIGUSR2 handler signal number = 12
 discribe signal:  User defined signal 2
setTextParentPID
setTextChildPID



catch signal handler signal number = 17
 discribe signal:  Child exited


Т.е я так понимаю работает нормально все.

А то у меня происходит обработка сигнала SIGCHLD, только после закрытия окна-процесса родителя.
« Последнее редактирование: Май 08, 2018, 10:09 от demaker » Записан
qate
Гипер активный житель
*****
Offline Offline

Сообщений: 887


Просмотр профиля
« Ответ #8 : Май 08, 2018, 12:19 »

можно попробовать обновить qt (или системно или с сайта qt)
обработка сигналов должна идти сразу после установки обработчика

я ставлю обработчик после создания qapp, но он только для корректного выхода (по сигналам SIGINT и SIGTERM)

Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 924


Просмотр профиля
« Ответ #9 : Май 08, 2018, 13:07 »

можно попробовать обновить qt (или системно или с сайта qt)
обработка сигналов должна идти сразу после установки обработчика

я ставлю обработчик после создания qapp, но он только для корректного выхода (по сигналам SIGINT и SIGTERM)

А код можно посмотреть Улыбающийся
Записан
qate
Гипер активный житель
*****
Offline Offline

Сообщений: 887


Просмотр профиля
« Ответ #10 : Май 10, 2018, 09:16 »

Код:
void signalhandler(int sig) {
if (sig == SIGINT || sig == SIGTERM)
qApp->exit();
}

int main(int argc, char *argv[])
{
signal(SIGINT, signalhandler); // Выход по требованию скрипта (ОС) Ctrl+c
signal(SIGTERM, signalhandler); // Выход по требованию ОС (крест или завершение программы при logout)
...

этим обеспечивается и нормальный выход и в креаторе при запуске/остановки приложения по "красному" квадрату
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Страница сгенерирована за 0.137 секунд. Запросов: 22.