Как я могу уничтожить 'системные' вызовы Perl, когда основной сценарий уничтожается?

Ткань должна вам помочь. В этом сервисе есть багтрекер, платформа для тестирования, аналитические сервисы и многое другое.

6
задан Community 23 May 2017 в 12:01
поделиться

3 ответа

Используйте setsid , чтобы сделать ваш процесс новым лидером группы. Затем вы можете отправить уничтожение идентификатору группы и уничтожить все процессы, принадлежащие этой группе. Все процессы, которые вы порождаете из процесса лидера, наследуют идентификатор группы и принадлежат к вашей недавно созданной группе. Таким образом, отправка убийства в группу убьет их всех. Единственная хитрость заключается в том, что для того, чтобы иметь возможность использовать setsid, вы должны закрыть свой стандарт на входе и выходе, так как это требование для setsid.

3
ответ дан 16 December 2019 в 21:46
поделиться
use strict;
use warnings;
setpgrp $$, 0;
system("sleep.pl");
END {kill 15, -$$}

Но если вам нужен такой подход, вы делаете что-то не так. Вы не должны этого делать. Вместо этого запустите и уничтожьте ваш процесс kill правильно.

$ perl -e 'system("sleep 100")' &
[1] 11928
$ ps f
  PID TTY      STAT   TIME COMMAND
 4564 pts/1    Ss     0:01 /bin/bash
11928 pts/1    S      0:00  \_ perl -e system("sleep 100")
11929 pts/1    S      0:00  |   \_ sleep 100
11936 pts/1    R+     0:00  \_ ps f
$ kill %1
[1]+  Terminated              perl -e 'system("sleep 100")'
$ ps f
  PID TTY      STAT   TIME COMMAND
 4564 pts/1    Rs     0:01 /bin/bash
11949 pts/1    R+     0:00  \_ ps f

Как это работает? Shell (bash в моем случае) должен установить ваш процесс в качестве лидера группы, если вы работаете в фоновом режиме. Тогда, если вы используете синтаксис kill%? , оболочка правильно убивает группу. Сравните это:

$ perl -e 'system("sleep 100")' &
[1] 12109
$ ps f
  PID TTY      STAT   TIME COMMAND
 4564 pts/1    Rs     0:01 /bin/bash
12109 pts/1    S      0:00  \_ perl -e system("sleep 100")
12113 pts/1    S      0:00  |   \_ sleep 100
12114 pts/1    R+     0:00  \_ ps f
$ kill 12109
[1]+  Terminated              perl -e 'system("sleep 100")'
$ ps f
  PID TTY      STAT   TIME COMMAND
 4564 pts/1    Ss     0:01 /bin/bash
12124 pts/1    R+     0:00  \_ ps f
12113 pts/1    S      0:00 sleep 100

Но kill%? работает следующим образом:

$ perl -e 'system("sleep 100")' &
[1] 12126
$ ps f
  PID TTY      STAT   TIME COMMAND
 4564 pts/1    Rs     0:01 /bin/bash
12126 pts/1    S      0:00  \_ perl -e system("sleep 100")
12127 pts/1    S      0:00  |   \_ sleep 100
12128 pts/1    R+     0:00  \_ ps f
$ kill -12126
[1]+  Terminated              perl -e 'system("sleep 100")'
$ ps f
  PID TTY      STAT   TIME COMMAND
 4564 pts/1    Ss     0:01 /bin/bash
12130 pts/1    R+     0:00  \_ ps f
3
ответ дан 16 December 2019 в 21:46
поделиться

Ваш вопрос действительно является конкретным примером более общего вопроса "как сделать так, чтобы ребенок умирал, когда умирает родитель". Без этого просто не обойтись. В system() нет ничего особенного; она просто форкает дочерний процесс и ждет его завершения.

system() выглядит примерно так:

sub system 
{
    my $kidpid = fork;
    if ( $kidpid )
    {
        waitpid $kidpid; 
          # parent process blocks here waiting for the child process to return
    }
    else
    {
        exec( @_ );
    }
}

Убийство группы процессов - ваш единственный выход.

2
ответ дан 16 December 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: