LINUX.ORG.RU

perl fork kill ???


0

0

Здравствуйте...
Сам не знаю что хочу:
есть что-то вроде такого:
#!/usr/bin/perl

unless(fork()) {
   #Тут ребенок
   exec("что-то большое и долгое");
   #не знаю нужен ли тут exit
   exit;
}
#Тут родитель
И при определенных условиях нужно ребенка убить. 
Как это сделать???
Я думал получить $pid=$$; ребенка а потом послать
ему kill('TERM', $pid);
Но ведь может так быть, что процесс ребенка закончится,
другой уже процесс получит тот же пид. И я убью не того...
★★

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

pid уникальный

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

> use wait, stupid
Dear clever guy.
Please, tell me in which line I should put function wait.

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

т.е. Уникальный???
от 0 до kernel.pid_max
а когда дошли до kernel.pid_max. то ОС начнет незанятые pid'ы выделять с начала.
fork создаст ребенка.. Родитель в это время работает сам по себе.
И в один прекрасный момент (непредсказуемый) ему может понадобится
убить ребенка (если тот еще есть).. Так времени может пройти столько
что ребенок уже завершился, pid свой освободил. ОС в раздаче pid'ов дошла до pid_max и начала с начала. Совершенно другой процесс получает
тот же пид и в это время parent решает что вот если тот ребенок
еще жив мне нужно его убить.. Но как это определить ???

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

>pid уникальный

ты не понял. уникальный на конкретный момент времени

при аптаймах выше месяца на машине под нагрузкой абсолютное большинство pid-ов будут попользованы по нескольку раз (или десятков раз, если нагрузка нехилая)

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

лови sigchield

в обработчике - wait()/waitpid()

если завершился интересующий тебя ребёнок - помечаеш что твой pid - недействительный

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

ну если у тебя дети будут работать месяцами, тогда слушай умных, а не меня :)

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

ok. 10x.
попробую..
да и кстати я похоже ошибся pid'ы от 1 до kenel.pid_max
2Pi: да ладно не прибедняйся.... :-)

tugrik ★★
() автор топика

1. fork возвращает пид ребёнка родителю, так что результат лучше запоминать. И проверять на -1 тоже стоит.

2. exit после exec не нужен, поскольку exec замещает текущий процесс.

3. Если процесс ребёнка закончился, то тебе надо сделать wait в обработчике SIGCHLD, иначе код возврата ребёнка будет торчать в таблице ожидая wait и ps будет показывать что у тебя в процессах есть зомби.

вообще, pelrdoc perlipc искать REAPER

Casus ★★★★★
()

IMHO чота вы переусложняете ;-)

tugrik может не беспокоиться, что какой-то новый
процесс получит тот же PID, что и давно почивший дочерний
процесс. Раз он не делает wait() то дочерний процесс так и будет
висеть в виде зомби и никто его PID повторно использовать не сможет.
Так вполне можно делать kill (ну и потом все-таки waitpid чтобы
убедиться, что дочерний процесс действительно завершен).

HTH

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

> 2. exit после exec не нужен, поскольку exec замещает текущий процесс.

Ну и зачем же так подставляться? :-)))
Конечно exit после exec _нужен_ - на случай того, что при exec
произойдет ошибка. Мы же не хотим, чтобы потом дочерний процесс
выполнял код, который он выпонять явно не должен.

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

> Конечно exit после exec _нужен_ - на случай того, что при exec

Ну если совсем правильно, то он нужен не после, а, так сказать, вместо ;)

exec($smth) || die "could not exec $smth: $!";

или как-то так.

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

> Ну и зачем же так подставляться? :-)))

А? Я? Я вообще за то, чтобы проверять код возврата/ошибки :)

Casus ★★★★★
()

2all.
Спасибо всем за коментарии..
Попытался исправиться: код выглядет на подобии вот этого:

$SIG{CHLD} = \&catch_chld;

if (!defined($d_pid = fork)) {
   die "cannot fork: $!";
} elsif (!$d_pid) {
   #Ребенок
   # exec вызывает что-то долгое типа такого:
   exec ("cat /dev/zero > /dev/null") or die "couldn't exec $!";
}
#Родитель
if (некое условие && $d_pid)
{
   system("killall cat");
   # если делаю kill('TERM', $d_pid); то ребенок умирает. НО exec ведь порождает
   # еще одного  ребенка поэтому процесс cat /dev/zero > /dev/null 
   # переходит к init т.е. ppid у него = 1.
}

sub catch_chld
{       
        wait();
        $d_pid = 0;
}
Если делаю как perlipc: while (waitpid(-1, WNOHANG)) { ; }
то процесс похоже виснет на while...

вкратце смысл такой что exec порождает еще одного ребенка.
И как убить их всех :-)  кроме родителя я не пойму...

p.s.
спасибо если кто вдруг разберется в том что я тут понаписал...

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

> #НО exec ведь порождает > # еще одного ребенка поэтому процесс cat /dev/zero > /dev/null > # переходит к init т.е. ppid у него = 1.

exec детей не порождает.

мож ты с system() спутал?

или пользуеш linuxthreads?

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

> exec детей не порождает.
Ну читал я что exec просто замещает текущий процесс.
Но что это такое???:
#!/usr/bin/perl -w
my $child_pid = 0;
if (!defined($child_pid = fork)) {
	die "cannot fork: $!";
} elsif (!$child_pid) {
	exec ("cat /dev/zero > /dev/null") or die "can't exec cat";
}
print "child_pid=$child_pid\n";
waitpid ($child_pid, 0);


$./test.pl
child_pid=22203

$ ps f -eo ppid,pid,cmd -www
 4200 17463                      \_ rxvt
17463 17464                      |   \_ bash
17464 22202                      |       \_ /usr/bin/perl -w ./test.pl
22202 22203                      |           \_ sh -c cat /dev/zero > /dev/null
22203 22204                      |               \_ cat /dev/zero

Т.е. теперь если мы сделаем до waitpid'a kill('TERM', $child_pid);
(т.е. то что мне нужно сделать завершить выполнения дочернего процесса при определенном условии).
то по сути мы убиваем 22203. 
22204 лешившись родителя переходит к init. 

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

>elsif (!$child_pid) {
>	exec ("cat /dev/zero > /dev/null") or die "can't exec cat";
>}

понял.

на скору руку попробуй так:

elsif (!$child_pid) {
	exec ("exec cat /dev/zero > /dev/null") or die "can't exec cat";
}

тоесть на самом деле ты вместо exec() делаеш system(). как дёргнуть exec() без предшествующего system() - не помню. почитай что нить или погугли

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

ну я конечно поищу еще более элегантное решение.
но впринципе, все работает... а я не ракеты в космос запускаю..
Так что мне это подойдет.

Большое спасибо...

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