URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 6468
[ Назад ]

Исходное сообщение
"Завершение работы и сигнал SIGTERM"

Отправлено oaealex , 16-Май-07 15:17 
Нужно отследить момент завершения работы/перезагрузки ОС Linux и корректно завершить работу моей программы. Программа ловит сигнал SIGTERM для этих целей.

Однако при reboot и halt мое приложение не получает этого сигнала, хотя есть сообщение
INIT: sending TERM signal

выдача команды killall myprog
приводит к обработеке моей программой сигнала SIGTERM

Такое ощущение - что "прибивается" родительский процесс для моей программы (bash) - что приводит к немедленному завершению моей программы.

Дело ослажняется тем - что программа должна запускаться автоматически при старте ситемы на терминале tty1.

Как корректно решаются такие проблеммы в LINUX ?

Алексей.


Содержание

Сообщения в этом обсуждении
"Завершение работы и сигнал SIGTERM"
Отправлено pavel_simple , 16-Май-07 15:37 
>Нужно отследить момент завершения работы/перезагрузки ОС Linux и корректно завершить работу моей
>программы. Программа ловит сигнал SIGTERM для этих целей.
>
>Однако при reboot и halt мое приложение не получает этого сигнала, хотя
>есть сообщение
>INIT: sending TERM signal
>
>выдача команды killall myprog
>приводит к обработеке моей программой сигнала SIGTERM
>
>Такое ощущение - что "прибивается" родительский процесс для моей программы (bash) -
>что приводит к немедленному завершению моей программы.
>
>Дело ослажняется тем - что программа должна запускаться автоматически при старте ситемы
>на терминале tty1.
>
>Как корректно решаются такие проблеммы в LINUX ?
>
>Алексей.

1. создай нормальный init скрипт с PID файлом и т.д. и т.п.
или
2. запускай прогу через inittab (сто не есть правильно -- но оно может именно то , что нужно)

З.Ы "родительский процесс для моей программы (bash) -" -- это что означает -- что программа есть шелл скрипт???


"Завершение работы и сигнал SIGTERM"
Отправлено V , 17-Май-07 02:27 
man init, man inittab и доки по sysvinit.



"Завершение работы и сигнал SIGTERM"
Отправлено oaealex , 17-Май-07 08:09 
>>Нужно отследить момент завершения работы/перезагрузки ОС Linux и корректно завершить работу моей
>1. создай нормальный init скрипт с PID файлом и т.д. и т.п.

Не понял, о чем идет речь. Нужно чтобы программа запускалась на терминале tty1

>или
>2. запускай прогу через inittab (сто не есть правильно -- но оно
>может именно то , что нужно)
Делаю следующее:
в /etc/inittab сторку
1:2345:respawn:/sbin/getty 38400 tty1
заменяю на
1:2345:respawn:/sbin/getty -n -l /etc/rc.d/autologinroot 38400 tty1
в файле autologinroot пишем
su -root -c "/bin/bash -li"
в каталоге /root создаю файл .bash_profile
if [ $(tty) == /dev/tty1 ] ; then
   cd /myprog
   /myprog/myprog
fi  

>З.Ы "родительский процесс для моей программы (bash) -" -- это что означает
>-- что программа есть шелл скрипт???

Нет - C++ приложение.
Может про родительский процесс я и "погнал" :) я в Linux  новичок.
Но по другому - обьяснить свои проблеммы не могу.


"Завершение работы и сигнал SIGTERM"
Отправлено pavel_simple , 17-Май-07 08:37 
а зачем getty использовать -- просто
1:2345:respawn:/myprog/myprog

или убери вовсе (закоментируй) "1:2345:respawn:/sbin/getty 38400 tty1" и запускай через screen -- ему можно указать на какой консоли робить.

А про PID -- так это обычно файлик такой -- в котором храниться информация о pid определённого запущенного процесса -- ну и обычно когда обрабатываются скрипты запуска/останова (init 3 ? init 5? init 6 ? init 0) -- так вот init6 (перезагрузка) и init0 (выключение) скрипты читают файлик -- и посылают сигнал процессу с этим пидом -- потом ждут когда процесс завершиться.


"Завершение работы и сигнал SIGTERM"
Отправлено oaealex , 17-Май-07 14:50 
>а зачем getty использовать -- просто
>1:2345:respawn:/myprog/myprog

Попробовал так (но через командный файл - связано с текущим каталогом) -
Моя программа запускается но имеются следующие побочные эффекты:
1) Прогамма не реагирует на на нажатия ^C (но может это даже к лучшему ;),
2) При выполнении reboot или halt моя программа успевает еще раз запуститься по respawn
на том терминале где делаем reboot.Что меня конечно не радует.
Похоже что в данном случае моя программа действительно получает SIGTERM но процесс init почемуто не смотря на то, что он собирается завершиться и перезапускает мое приложение.

Кстати это по моему подтверждает гипотезу - что при моем способе запуска я не ловлю своим процессом SIGTERM именно потому, что bash "умирает" первым - и "прибивает" своих "деток".

>или убери вовсе (закоментируй) "1:2345:respawn:/sbin/getty 38400 tty1" и запускай через screen --
>ему можно указать на какой консоли робить.

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

>
>А про PID -- так это обычно файлик такой -- в котором
>храниться информация о pid определённого запущенного процесса -- ну и обычно
>когда обрабатываются скрипты запуска/останова (init 3 ? init 5? init 6
>? init 0) -- так вот init6 (перезагрузка) и init0 (выключение)
>скрипты читают файлик -- и посылают сигнал процессу с этим пидом
>-- потом ждут когда процесс завершиться.

Это понятно - но как я понял - эти скрипты выполняются уже ПОСЛЕ того как были разосланы синалы SIGTERN и SIGKILL процессом init. И мой анализ PID в этих скриптах уже бессмысленен, т.к. приложение уже "умерло" не попрощавшись :)

В этом то ПОСЛЕ  как раз и вся "засада".


"Завершение работы и сигнал SIGTERM"
Отправлено pavel_simple , 17-Май-07 15:19 
а вот теперь надо учиться учиться и ещё раз учиться

"Завершение работы и сигнал SIGTERM"
Отправлено oaealex , 17-Май-07 15:33 
>>а зачем getty использовать -- просто
>Моя программа запускается но имеются следующие побочные эффекты:
>1) Прогамма не реагирует на нажатия ^C (но может это даже
>к лучшему ;),
>2) При выполнении reboot или halt моя программа успевает еще раз запуститься
>по respawn

п.1 - верно
п.2 - мой "косяк" - в процессе экспериментов - перенаправлял reboot и halt на свои скрипты - "убийцы" myprog :)

Короче правильно остановить программу - сделать так - как говорили умные люди :)
1) строку inittab 1:2345:respawn:/sbin/getty 38400 tty1
   заменяем на 1:2345:respawn:/myprog/run_myprog
2) в скрипте /myprog/run_myprog пишем
#!/bin/bash
cd /myprog
/myprog/myprog

3) ну и не забываем в  теле программы установить обработчик SIGTERM

Единственно что нужно учитывать - пауза между TERM и KILL сигналами выдаваемыми процессом init - достаточно мала. Заставитьбы init перед KILL дожидаться завершения моей myprog - былобы совсем хорошо.


"Завершение работы и сигнал SIGTERM"
Отправлено NuINu , 17-Май-07 15:46 

>Это понятно - но как я понял - эти скрипты выполняются уже
>ПОСЛЕ того как были разосланы синалы SIGTERN и SIGKILL процессом init.
>И мой анализ PID в этих скриптах уже бессмысленен, т.к. приложение
>уже "умерло" не попрощавшись :)
>
>В этом то ПОСЛЕ  как раз и вся "засада".

Я думаю тебе поможет правильная демонизация твоего процесса!
Почему у тебя родительский процесс bash?? из за того что ты его из basha запустил? демонизируешь свою прогу и все корректно будет получать сигтерм!

Поясни пожалуйста что значит
"Нужно чтобы программа запускалась на терминале tty1"
что это за программа? она обслуживает работу tty1? На нем больше кроме нее никто не работает? Твоя прога его на запись открывает? или она использует STDOUT полученный от bash, а тот получивший его в наследство от login, в свою очередь получивший от getty?

Если нужно работать с tty1, то (ИМХО) надо убрать с tty1 всех этих демонов(вернее только getty :))! и открывать его через open 'dev/tty1'

если ты правильно выполнишь демонизацию своей проги, то ее родителем станет 1 процесс init, а значит она не умрет из за того что ее родителя скропостижно убили.

Вот проверь этот скрипт:
#!/usr/bin/perl -w

use strict;
use POSIX 'WNOHANG';

my $quit = 0;

print "----------Base Start Programm------------------\n";

open(LOG, ">>", "daemon.log");
#Отвязываемся от вывода в текущи терминал
open(STDIN,  '</dev/null')   or die "Can't read /dev/null: $!";
open(STDOUT, ">>&LOG")   or die "Can't write to LOG file: $!";
open(STDERR, ">>&LOG")   or die "Can't error to LOG file: $!";
umask(0);           #Сброс маски режима создания файлов
$ENV{PATH} = '/bin:/usr/bin';
#Выходим из текущего потока управления, создавая свой, а в текущем завершаемся.
die "Can't fork" unless defined (my $child = fork());
if($child) {
    print "close parent, and stay demon";
    exit 0;         #Завершение родительского сеанса
}
#становимся лидером сессии
POSIX::setsid();


sub sig_worker {
    my $sig = shift;
    $quit++;
    print "I get signal = $sig\n";
    return;
}

#Устанавливаем обработчик сигналов
$SIG{TERM} = $SIG{INT} = \&sig_worker;

while(!$quit){
    print "Please: Kill me!!!\n";
    sleep 1;
}
    #Определим причину по которой завершилась программа
if($quit) {
    print "Exit by quit = $quit\n";
}

print "---------------- End Programm---------------------\n";
close(LOG);
exit(0);