Написал простую программку для исследования работы сигналов в ОС Линукс
Вот код программы:
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()