diff --git a/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm b/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm index ff79ac1..601b414 100644 --- a/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm +++ b/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm @@ -214,6 +214,12 @@ sub lock_section { sub stat { shift->_shared_memory->stat } -sub DESTROY { $_[0]->remove if $_[0]->destroy() } +sub DESTROY { + my $self = shift; + if ($self->_shared_memory) { + eval { $self->_shared_memory->detach() }; + } + $self->remove if $self->destroy(); +} !!42; diff --git a/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm b/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm index 7ca9636..877fd1a 100644 --- a/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm +++ b/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm @@ -25,14 +25,19 @@ sub _genkey { ftok($0, 0) } sub _create { my ($self, $key) = @_; - # Try acquiring already existing semaphore - my $sem = IPC::Semaphore->new($key, $self->count, 0); - unless (defined $sem) { + # Try creating it. IPC_EXCL in flags fails with EEXIST if it already + # exists, e.g. from a previous call, or a concurrent process that won the + # race to create it - both cases are handled the same way: attach to it. + my $sem = IPC::Semaphore->new($key, $self->count, $self->flags); + if (defined $sem) { warn "[debug:$$] Create semaphore $key" if DEBUG; - $sem = IPC::Semaphore->new($key, $self->count, $self->flags); - confess 'Semaphore creation failed! ' unless defined($sem); $sem->setall($self->_value); } + else { + warn "[debug:$$] Attach to existing semaphore $key" if DEBUG; + $sem = IPC::Semaphore->new($key, $self->count, 0); + } + confess 'Semaphore creation failed! ' unless defined($sem); return $sem; } diff --git a/t/02_parallel.t b/t/02_parallel.t index 6f3c52c..b877c1b 100644 --- a/t/02_parallel.t +++ b/t/02_parallel.t @@ -70,7 +70,7 @@ subtest batch => sub { separate_err => 0, set_pipes => 1 ); - $c->start(); + $c->last->start(); is $c->last->getline, "Hello world 3\n"; $c->wait_stop();