Хранить несколько элементов в объекте IPC :: ShareLite - PullRequest
0 голосов
/ 26 марта 2019

У меня есть программа Perl, которая разветвляет подпроцессы и обрабатывает в них N элементов, после чего мне нужно вернуть эти обработанные элементы в основной процесс.

Из нескольких доступных опций IPC для возврата обработанных элементов в основной процесс, IPC :: ShareLite представляется наиболее простым, но я не уверен, поддерживает ли он хранение нескольких элементов в одном общем объекте.

Вот фрагмент программы, но он не работает:

use IPC::ShareLite;

# create shared object in main process
my $share = new IPC::ShareLite(
    -key     => 1234,
    -create  => 'yes',
    -destroy => 'yes'
) or die $!;

# fork subprocesses, process and store N items in shared object
$share->store($member);

# After subprocesses finish, fetch items in main process
my $members_size = scalar @$members_ref;
@$members_ref = ();
while ($members_size > 0) {
    my $member = $share->fetch();
    push @$members_ref, $member;
    $members_size--;
}

Вышеприведенный код завершается с довольно неясной ошибкой my $member = $share->fetch();:

IPC :: ShareLite fetch () ошибка: неверный аргумент в ...

Можно ли использовать объект IPC :: ShareLite, как я намереваюсь, или он может содержать только один элемент?

1 Ответ

2 голосов
/ 26 марта 2019

Вы создаете дочерний элемент, используя fork, и этот дочерний элемент получает копию объекта $share.Когда дочерний процесс завершается, дочерняя копия объекта $share уничтожается, что приводит к уничтожению базовых системных ресурсов, поскольку вы использовали -destroy => 'yes'.

В общем случае вы хотите создавать объекты с деструкторами после выполнения вилок.

Но при создании объекта IPC :: ShareLite вы обычно хотите оставить ключ, чтобы система могла выбрать ключ для вас, но вы должны сделать это перед созданиемвилки.

Обходной путь

Выполните следующие действия в отношении ребенка:

$share->destroy(0);

Лучшее решение

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

Для этого необходимо, чтобы сопровождающий модуля изменил модуль так, чтобы уничтожение происходило только в том случае, если текущий PID совпадает с PID, в котором был создан $share.

sub _initialize {
  ...
  $self->{pid} = $$;   # ADD
  ...
}

sub DESTROY {
  my $self = shift;

  #destroy_share( $self->{share}, $self->{destroy} )                           # REMOVE
  destroy_share( $self->{share}, $self->{pid} == $$ ? $self->{destroy} : 0 )   # ADD
   if $self->{share};
}
...