Perl: вилка из параллельных потоков - PullRequest
1 голос
/ 14 октября 2019

Ниже код должен запускать 2 параллельных потока, каждый поток выполняет fork (), ожидает завершения дочернего процесса, затем ожидается, что потоки присоединятся (завершить), и результат будет напечатан. В действительности, первый разветвленный дочерний процесс завершается, как и ожидалось, но второй зависает при _mutex_lock (), пытающемся выйти, поэтому второй поток никогда не присоединяется, пока вы не убьете второго потомка вручную с сигналом -9. Может кто-нибудь объяснить, почему это происходит и как этого избежать?

use strict;
use warnings;
use threads;
use Data::Dumper;

sub Run
{
    my $tid = threads->tid();
    my $log = {};
    $log->{"[$$:$tid]:00"} = "started";
    my $pid = fork();
    if ($pid == 0)
    {
         print "In child ($$): started\n";
         sleep 3;
         print "In child ($$): finished\n";
#         system("kill -9 $$");  -- brutal way
         exit 0;
    }
    waitpid($pid, 0);
    my $exitCode = $? >> 8;
    $log->{"[$$:$tid]:01"} = "finished, code=$exitCode";
    return $log;
}

my @threads = ();
foreach (1..2)
{
    push @threads, threads->new(sub { return Run() });
}
print Dumper($_->join()) for @threads;

1 Ответ

6 голосов
/ 14 октября 2019

На моем компьютере с Linux работает _exit из POSIX вместо exit . Однако это решение может быть непереносимым на другие платформы.

В связанной документации написано:

Обратите внимание, что при использовании потоков и в Linux это не хороший способ выхода изпоток, потому что в Linux процессы и потоки являются чем-то вроде одного и того же (Примечание: хотя в начале 2003 года это происходило, существуют проекты, в которых потоки имеют больше семантики POSIXly в Linux). Если вы не хотите возвращаться из потока, отсоедините поток.

Аналогично, perlthrtut - Руководство по потокам в Perl говорит

Думая осмешивание fork () и потоков? Пожалуйста, лягте и подождите, пока чувство не пройдет. Помните, что семантика fork () варьируется в зависимости от платформы. Например, некоторые системы Unix копируют все текущие потоки в дочерний процесс, в то время как другие копируют только поток, вызвавший fork (). Вы были предупреждены!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...