diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/Changes libmojo-ioloop-readwriteprocess-perl-0.27/Changes --- libmojo-ioloop-readwriteprocess-perl-0.25/Changes 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/Changes 2020-07-03 00:27:21.000000000 +0000 @@ -1,5 +1,15 @@ + Revision history for Perl extension Mojo-IOLoop-ReadWriteProcess +0.27 2020-07-03T00:25:15Z + - Fix CircleCI build + - Fix perl required version + +0.26 2020-07-02T18:21:18Z + - Apply tools/tidy with Perl::Tidy 20200110 + - Allow stopping the entire process group of the process + - Change minimum perl to 5.16 + 0.25 2020-04-08T14:48:01Z - In "stop" sleep only after sending the first signal to speedup termination by okurz - Various fixups in test suite diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/circle.yml libmojo-ioloop-readwriteprocess-perl-0.27/circle.yml --- libmojo-ioloop-readwriteprocess-perl-0.25/circle.yml 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/circle.yml 2020-07-03 00:27:21.000000000 +0000 @@ -1,19 +1,24 @@ -machine: - environment: - PATH: ~/perl5/bin:$PATH - -dependencies: - pre: - - curl -L https://cpanmin.us | perl - App::cpanminus - - cpanm --local-lib=~/perl5 local::lib && echo "eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)" >> ~/.bashrc - - cpanm --quiet --notest --skip-satisfied Devel::Cover Devel::Cover::Report::Codecov - - cpanm --installdeps . - -test: - override: - - perl Build.PL - - ./Build build - - cover -test - - post: - - cover -report codecov +version: 2.1 +orbs: + perl: circleci/perl@1.0.0 +workflows: + main: + jobs: + - perl/build: + codecov: true + save-to-artifacts: true + save-to-workspace: true + - perl/test-linux: + matrix: + parameters: + perl-version: + - '5.16' + - '5.18' + - '5.20' + - '5.22' + - '5.24' + - '5.26' + - '5.28' + - '5.30' + requires: + - perl/build \ No newline at end of file diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/cpanfile libmojo-ioloop-readwriteprocess-perl-0.27/cpanfile --- libmojo-ioloop-readwriteprocess-perl-0.25/cpanfile 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/cpanfile 2020-07-03 00:27:21.000000000 +0000 @@ -3,7 +3,7 @@ on configure => sub { requires 'Module::Build'; - requires 'perl', '5.008_001'; + requires 'perl', '5.016'; }; on test => sub { diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/debian/changelog libmojo-ioloop-readwriteprocess-perl-0.27/debian/changelog --- libmojo-ioloop-readwriteprocess-perl-0.25/debian/changelog 2020-06-02 15:10:54.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/debian/changelog 2020-07-06 11:52:07.000000000 +0000 @@ -1,3 +1,9 @@ +libmojo-ioloop-readwriteprocess-perl (0.27-1) unstable; urgency=medium + + * New upstream version 0.27 + + -- Hideki Yamane Mon, 06 Jul 2020 20:52:07 +0900 + libmojo-ioloop-readwriteprocess-perl (0.25-3) unstable; urgency=medium * debian/control diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Freezer.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Freezer.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Freezer.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Freezer.pm 2020-07-03 00:27:21.000000000 +0000 @@ -10,7 +10,7 @@ has cgroup => sub { Mojo::IOLoop::ReadWriteProcess::CGroup::v1->new }; -sub state { shift->cgroup->_setget(STATE_INTERFACE, @_) } +sub state { shift->cgroup->_setget(STATE_INTERFACE, @_) } sub self_freezing { shift->cgroup->_list(SELF_FREEZING_INTERFACE) } sub parent_freezing { shift->cgroup->_list(PARENT_FREEZING_INTERFACE) } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Memory.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Memory.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Memory.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Memory.pm 2020-07-03 00:27:21.000000000 +0000 @@ -99,10 +99,10 @@ sub move_charge { shift->cgroup->_setget(MOVE_CHARGE_AT_IMMIGRATE_INTERFACE, @_); } -sub oom_control { shift->cgroup->_setget(OOM_CONTROL_INTERFACE, @_) } -sub numa_stat { shift->cgroup->_list(NUMA_STAT_INTERFACE) } -sub kmem_limit { shift->cgroup->_setget(KMEM_LIMIT_INTERFACE, @_) } -sub kmem_usage { shift->cgroup->_list(KMEM_USAGE_INTERFACE) } +sub oom_control { shift->cgroup->_setget(OOM_CONTROL_INTERFACE, @_) } +sub numa_stat { shift->cgroup->_list(NUMA_STAT_INTERFACE) } +sub kmem_limit { shift->cgroup->_setget(KMEM_LIMIT_INTERFACE, @_) } +sub kmem_usage { shift->cgroup->_list(KMEM_USAGE_INTERFACE) } sub kmem_failcnt { shift->cgroup->_list(KMEM_FAILCNT_INTERFACE) } sub kmem_max_usage { shift->cgroup->_list(KMEM_MAX_RECORDED_INTERFACE) } sub kmem_tcp_limit { shift->cgroup->_setget(KMEM_TCP_LIMIT_INTERFACE, @_) } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Netprio.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Netprio.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Netprio.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/Netprio.pm 2020-07-03 00:27:21.000000000 +0000 @@ -11,7 +11,7 @@ has cgroup => sub { Mojo::IOLoop::ReadWriteProcess::CGroup::v1->new }; sub ifpriomap { shift->cgroup->_setget(IFPRIOMAP_INTERFACE, @_) } -sub prioidx { shift->cgroup->_list(PRIOIDX_INTERFACE) } +sub prioidx { shift->cgroup->_list(PRIOIDX_INTERFACE) } 1; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/PID.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/PID.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/PID.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1/PID.pm 2020-07-03 00:27:21.000000000 +0000 @@ -7,7 +7,7 @@ has cgroup => sub { Mojo::IOLoop::ReadWriteProcess::CGroup::v2->new }; sub current { shift->cgroup->_list(CURRENT_INTERFACE) } -sub max { shift->cgroup->_setget(MAX_INTERFACE, @_) } +sub max { shift->cgroup->_setget(MAX_INTERFACE, @_) } 1; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v1.pm 2020-07-03 00:27:21.000000000 +0000 @@ -27,9 +27,14 @@ has controller => ''; sub _cgroup { - path($_[0]->parent - ? - path($_[0]->_vfs, $_[0]->controller // '', $_[0]->name // '', $_[0]->parent) + path( + $_[0]->parent + ? path( + $_[0]->_vfs, + $_[0]->controller // '', + $_[0]->name // '', + $_[0]->parent + ) : path($_[0]->_vfs, $_[0]->controller // '', $_[0]->name // '')); } @@ -44,7 +49,7 @@ my ($self, $string) = @_; my $g = $self->_vfs; $string =~ s/$g//; - my @p = splitdir($string); + my @p = splitdir($string); my $pre = substr $string, 0, 1; shift @p if $pre eq '/'; my $controller = shift @p; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/PID.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/PID.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/PID.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/PID.pm 2020-07-03 00:27:21.000000000 +0000 @@ -7,7 +7,7 @@ has cgroup => sub { Mojo::IOLoop::ReadWriteProcess::CGroup::v2->new }; sub current { shift->cgroup->_list(CURRENT_INTERFACE) } -sub max { shift->cgroup->_setget(MAX_INTERFACE, @_) } +sub max { shift->cgroup->_setget(MAX_INTERFACE, @_) } 1; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/RDMA.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/RDMA.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/RDMA.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup/v2/RDMA.pm 2020-07-03 00:27:21.000000000 +0000 @@ -8,7 +8,7 @@ has cgroup => sub { Mojo::IOLoop::ReadWriteProcess::CGroup::v2->new }; sub current { shift->cgroup->_list(CURRENT_INTERFACE) } -sub max { shift->cgroup->_setget(MAX_INTERFACE, @_) } +sub max { shift->cgroup->_setget(MAX_INTERFACE, @_) } 1; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/CGroup.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/CGroup.pm 2020-07-03 00:27:21.000000000 +0000 @@ -24,7 +24,7 @@ my ($self, $string) = @_; my $g = $self->_vfs; $string =~ s/$g//; - my @p = splitdir($string); + my @p = splitdir($string); my $pre = substr $string, 0, 1; shift @p if $pre eq '/'; my $name = shift @p; @@ -32,8 +32,8 @@ } sub _cgroup { - path($_[0]->parent ? - path($_[0]->_vfs, $_[0]->name // '', $_[0]->parent) + path($_[0]->parent + ? path($_[0]->_vfs, $_[0]->name // '', $_[0]->parent) : path($_[0]->_vfs, $_[0]->name // '')); } @@ -60,8 +60,8 @@ print $h ($f == 0 ? 0 : 1); } -sub _appendln { shift->_append(shift() => pop() . "\n") } -sub _list { my $c = shift->_cgroup->child(pop); $c->slurp if -e $c } +sub _appendln { shift->_append(shift() => pop() . "\n") } +sub _list { my $c = shift->_cgroup->child(pop); $c->slurp if -e $c } sub _listarray { split(/\n/, shift->_list(@_)) } sub _contains { @@ -71,8 +71,8 @@ } sub _setget { - $_[2] ? - shift->_cgroup->child($_[0])->spurt($_[1]) + $_[2] + ? shift->_cgroup->child($_[0])->spurt($_[1]) : shift->_cgroup->child($_[0])->slurp; } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Container.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Container.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Container.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Container.pm 2020-07-03 00:27:21.000000000 +0000 @@ -109,7 +109,7 @@ set_pipes => 0, internal_pipes => 1, code => sub { - $_[0]->enable_subreaper if $self->subreaper; + $_[0]->enable_subreaper if $self->subreaper; $self->namespace->isolate() if $self->unshare & CLONE_NEWNS; $fn->(@_); }); diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Namespace.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Namespace.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Namespace.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Namespace.pm 2020-07-03 00:27:21.000000000 +0000 @@ -41,8 +41,7 @@ my $prctl_call = $machine =~ /^i[3456]86|^blackfin|cris|frv|h8300|m32r|m68k|microblaze|mn10300|sh|parisc$/ - ? - 310 + ? 310 : $machine eq "s390" ? 303 : $machine eq "x86_64" ? 272 @@ -109,7 +108,7 @@ 0); warn "mount is unavailable on this platform." if $!{EINVAL}; - warn "Mount failed! $!" if $!; + warn "Mount failed! $!" if $!; return $ret; } @@ -119,7 +118,7 @@ my $ret = syscall(_get_unshare_syscall(), $opts, 0, 0); warn "unshare is unavailable on this platform." if $!{EINVAL}; - warn "Unshare failed! $!" if $!; + warn "Unshare failed! $!" if $!; return $ret; } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Queue.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Queue.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Queue.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Queue.pm 2020-07-03 00:27:21.000000000 +0000 @@ -57,8 +57,7 @@ return ( eval { $self->pool->Mojo::IOLoop::ReadWriteProcess::Pool::_cmd(@_, $fn) }, (grep(/once|on|emit/, $fn)) - ? - eval { $self->queue->Mojo::IOLoop::ReadWriteProcess::Pool::_cmd(@_, $fn) } + ? eval { $self->queue->Mojo::IOLoop::ReadWriteProcess::Pool::_cmd(@_, $fn) } : ()); } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Session.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Session.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Session.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Session.pm 2020-07-03 00:27:21.000000000 +0000 @@ -53,7 +53,7 @@ while ((my $pid = waitpid(-1, WNOHANG)) > 0) { $singleton->collect($pid => $? => $!); } - } + } }); } @@ -91,8 +91,8 @@ sub _resolve { my ($el, $w) = (pop, pop); return - exists $singleton->{$w}->{$el} ? - $w eq 'orphans' + exists $singleton->{$w}->{$el} + ? $w eq 'orphans' ? $singleton->{$w}->{$el} : ${$singleton->{$w}->{$el}} : undef; @@ -149,18 +149,18 @@ = $machine =~ /^i[3456]86|^blackfin|cris|frv|h8300|m32r|m68k|microblaze|mn10300|sh|s390|parisc$/ ? 172 - : $machine eq "x86_64" ? 157 - : $machine eq "sparc64" ? 147 - : $machine eq "aarch64" ? 167 + : $machine eq "x86_64" ? 157 + : $machine eq "sparc64" ? 147 + : $machine eq "aarch64" ? 167 : ($machine eq "ppc" || $machine eq "ppc64le") ? 171 - : $machine eq "ia64" ? 1170 - : $machine eq "alpha" ? 348 - : $machine eq "arm" ? 0x900000 + 172 - : $machine eq "avr32" ? 148 - : $machine eq "mips" ? 4000 + 192 - : $machine eq "mips64" ? 5000 + 153 - : $machine eq "xtensa" ? 130 - : undef; + : $machine eq "ia64" ? 1170 + : $machine eq "alpha" ? 348 + : $machine eq "arm" ? 0x900000 + 172 + : $machine eq "avr32" ? 148 + : $machine eq "mips" ? 4000 + 192 + : $machine eq "mips64" ? 5000 + 153 + : $machine eq "xtensa" ? 130 + : undef; unless (defined $prctl_call) { delete @INC{ @@ -188,7 +188,7 @@ ($arg5 or 0)); warn "prctl($option) is unavailable on this platform." if $!{EINVAL}; - warn "Error! $!" if $!; + warn "Error! $!" if $!; return $ret; } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Lock.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Lock.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Lock.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Lock.pm 2020-07-03 00:27:21.000000000 +0000 @@ -19,7 +19,7 @@ warn "[debug:$$] Attempt to acquire lock " . $self->key if DEBUG; my $r = @_ > 0 ? $self->acquire(@_) : $self->acquire(wait => 1, undo => 0); warn "[debug:$$] lock Returned : $r" if DEBUG; - $self->locked(1) if defined $r && $r == 1; + $self->locked(1) if defined $r && $r == 1; return $r; } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Memory.pm 2020-07-03 00:27:21.000000000 +0000 @@ -19,7 +19,7 @@ has flags => S_IRWXU() | S_IRWXG() | IPC_CREAT(); has lock_flags => IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; -has _size => 10 * 1024; +has _size => 10 * 1024; has _shared_memory => sub { $_[0]->_newmem() }; has _shared_size => sub { $_[0]->_newmem((2 * shift->key) - 1, $Config{intsize}) }; @@ -59,7 +59,7 @@ sub _readsize { my $self = shift; - my $s = $self->_shared_size()->read(0, $Config{intsize}); + my $s = $self->_shared_size()->read(0, $Config{intsize}); return unpack('I', $s); } @@ -132,7 +132,7 @@ warn "[debug:$$] Error Saving data : $@" if $@ && DEBUG; $_[0]->_shared_memory->detach() if $_[0]->_shared_memory; - return if $@; + return if $@; return 1; } @@ -159,7 +159,7 @@ }; warn "[debug:$$] Error Loading data : $@" if $@ && DEBUG; - return if $@; + return if $@; return 1; } @@ -191,7 +191,7 @@ shift->_lock->unlock(@_); } -sub lock { my $s = shift; my $r = $s->_lock->lock(@_); $s->load; $r } +sub lock { my $s = shift; my $r = $s->_lock->lock(@_); $s->load; $r } sub try_lock { $_[0]->_lock->try_lock() } sub lock_section { diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess/Shared/Semaphore.pm 2020-07-03 00:27:21.000000000 +0000 @@ -54,7 +54,7 @@ if ($args{'wait'}) { my $ncnt = $self->getncnt($args{'sem'}); return if ($args{'max'} >= 0 && $ncnt >= $args{'max'}); - warn "[debug:$$] Semaphore wait" if DEBUG; + warn "[debug:$$] Semaphore wait" if DEBUG; warn "[debug:$$] Semaphore val " . $self->getval($args{sem}) if DEBUG; # Remove NOWAIT and block diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess.pm libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/lib/Mojo/IOLoop/ReadWriteProcess.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/lib/Mojo/IOLoop/ReadWriteProcess.pm 2020-07-03 00:27:21.000000000 +0000 @@ -1,6 +1,6 @@ package Mojo::IOLoop::ReadWriteProcess; -our $VERSION = '0.25'; +our $VERSION = '0.27'; use Mojo::Base 'Mojo::EventEmitter'; use Mojo::File 'path'; @@ -22,6 +22,7 @@ use IO::Pipe; use IO::Select; use IPC::Open3; +use Time::HiRes 'sleep'; use Symbol 'gensym'; use Storable; use POSIX qw( :sys_wait_h :signal_h ); @@ -37,7 +38,7 @@ qw(internal_pipes channels) ] => 1; -has [qw(blocking_stop serialize quirkiness)] => 0; +has [qw(blocking_stop serialize quirkiness total_sleeptime_during_kill)] => 0; has [ qw(execute code process_id pidfile return_status), @@ -46,6 +47,7 @@ ]; has max_kill_attempts => 5; +has kill_whole_group => 0; has args => sub { [] }; has error => sub { Mojo::Collection->new }; @@ -135,8 +137,8 @@ $self->read_stream(IO::Handle->new_from_fd($rdr, "r")); $self->write_stream(IO::Handle->new_from_fd($wtr, "w")); - $self->error_stream(($self->separate_err) ? - IO::Handle->new_from_fd($err, "r") + $self->error_stream(($self->separate_err) + ? IO::Handle->new_from_fd($err, "r") : $self->write_stream); return $self; @@ -175,23 +177,23 @@ if ($self->_internal_return) { $return_reader - = $self->_internal_return->isa("IO::Pipe::End") ? - $self->_internal_return + = $self->_internal_return->isa("IO::Pipe::End") + ? $self->_internal_return : $self->_internal_return->reader(); $self->_new_err('Cannot read from return code pipe') && return unless IO::Select->new($return_reader)->can_read(10); $rt = $return_reader->getline(); $self->_diag("Forked code Process Returns: " . ($rt ? $rt : 'nothing')) if DEBUG; - $self->return_status($self->serialize ? - eval { $self->_deserialize->(b64_decode($rt)) } - : $rt ? $rt - : ()); + $self->return_status( + $self->serialize ? eval { $self->_deserialize->(b64_decode($rt)) } + : $rt ? $rt + : ()); } if ($self->_internal_err) { $internal_err_reader - = $self->_internal_err->isa("IO::Pipe::End") ? - $self->_internal_err + = $self->_internal_err->isa("IO::Pipe::End") + ? $self->_internal_err : $self->_internal_err->reader(); $self->_new_err('Cannot read from errors code pipe') && return unless IO::Select->new($internal_err_reader)->can_read(10); @@ -263,8 +265,8 @@ if ($self->internal_pipes) { if ($self->_internal_err) { $internal_err - = $self->_internal_err->isa("IO::Pipe::End") ? - $self->_internal_err + = $self->_internal_err->isa("IO::Pipe::End") + ? $self->_internal_err : $self->_internal_err->writer(); $internal_err->autoflush(1); } @@ -272,8 +274,7 @@ if ($self->_internal_return) { $return = $self->_internal_return->isa("IO::Pipe::End") - ? - $self->_internal_return + ? $self->_internal_return : $self->_internal_return->writer(); $return->autoflush(1); } @@ -291,8 +292,8 @@ $stdout = $output_pipe->writer() if $output_pipe; $stderr = (!$self->separate_err) ? $stdout - : $output_err_pipe ? $output_err_pipe->writer() - : undef; + : $output_err_pipe ? $output_err_pipe->writer() + : undef; $stdin = $input_pipe->reader() if $input_pipe; open STDERR, ">&", $stderr or !!$internal_err->write($!) @@ -383,15 +384,15 @@ } sub wait_stop { shift->wait->stop } -sub errored { !!@{shift->error} ? 1 : 0 } +sub errored { !!@{shift->error} ? 1 : 0 } # PPC64: Treat msb on neg (different cpu/perl interpreter version) sub _st { my $st = shift >> 8; ($st & 0x80) ? (0x100 - ($st & 0xFF)) : $st } sub exit_status { defined $_[0]->_status && $_[0]->quirkiness ? _st(shift->_status) - : defined $_[0]->_status ? shift->_status >> 8 - : undef; + : defined $_[0]->_status ? shift->_status >> 8 + : undef; } sub restart { @@ -465,8 +466,8 @@ die "Nothing to do" unless !!$self->execute || !!$self->code; my @args - = $self->args ? - ref($self->args) eq "ARRAY" + = $self->args + ? ref($self->args) eq "ARRAY" ? @{$self->args} : $self->args : (); @@ -490,58 +491,64 @@ sub send_signal { my $self = shift; my $signal = shift // $self->_default_kill_signal; - return unless $self->is_running; - $self->_diag("Sending signal '$signal' to " . $self->process_id) if DEBUG; - kill $signal => $self->process_id; + my $pid = shift // $self->process_id; + return unless $self->kill_whole_group || $self->is_running; + $self->_diag("Sending signal '$signal' to $pid") if DEBUG; + kill $signal => $pid; return $self; } sub stop { my $self = shift; - return $self unless defined $self->pid; - - $self->_diag("Stopping " . $self->pid) if DEBUG; - + my $pid = $self->pid; + return $self unless defined $pid; return $self->_shutdown(1) unless $self->is_running; + $self->_diag("Stopping $pid") if DEBUG; my $ret; - my $attempt = 1; - until ((defined $ret && $ret == $self->process_id) - || !$self->is_running - || $attempt > $self->max_kill_attempts) + my $attempt = 1; + my $timeout = $self->total_sleeptime_during_kill // 0; + my $sleep_time = $self->sleeptime_during_kill; + my $max_attempts = $self->max_kill_attempts; + my $signal = $self->_default_kill_signal; + $pid = -getpgrp($pid) if $self->kill_whole_group; + until ((defined $ret && ($ret == $pid || $ret == -1)) + || ($attempt > $max_attempts && $timeout <= 0)) { - $self->_diag("attempt ($attempt/" - . $self->max_kill_attempts - . ") to kill process: " - . $self->pid) - if DEBUG; + my $send_signal = $attempt == 1 || $timeout <= 0; + $self->_diag( + "attempt $attempt/$max_attempts to kill process: $pid, timeout: $timeout") + if DEBUG && $send_signal; $self->session->_protect( sub { local $?; - $self->send_signal(); - $ret = waitpid($self->process_id, WNOHANG); - $self->_status($?) if $ret == $self->process_id; + if ($send_signal) { + $self->send_signal($signal, $pid); + ++$attempt; + } + $ret = waitpid($pid, WNOHANG); + $self->_status($?) if $ret == $pid || $ret == -1; }); - $attempt++; - sleep $self->sleeptime_during_kill if $self->sleeptime_during_kill; + if ($sleep_time) { + sleep $sleep_time; + $timeout -= $sleep_time; + } } sleep $self->kill_sleeptime if $self->kill_sleeptime; - if ($self->blocking_stop && $self->is_running) { - $self->_diag( - "Could not kill process id: " . $self->process_id . ", blocking attempt") - if DEBUG; + if ($self->blocking_stop) { + $self->_diag("Could not kill process id: $pid, blocking attempt") if DEBUG; $self->emit('process_stuck'); ### XXX: avoid to protect on blocking. - $self->send_signal($self->_default_blocking_signal); - $ret = waitpid($self->process_id, 0); - $self->_status($?) if $ret == $self->process_id; + $self->send_signal($self->_default_blocking_signal, $pid); + $ret = waitpid($pid, 0); + $self->_status($?) if $ret == $pid || $ret == -1; } - elsif ($self->is_running) { - $self->_diag("Could not kill process id: " . $self->process_id) if DEBUG; + else { + $self->_diag("Could not kill process id: $pid") if DEBUG; $self->_new_err('Could not kill process'); } @@ -856,6 +863,20 @@ It can be used with blocking_stop, so if the number of attempts are exhausted, a SIGKILL and waitpid will be tried at the end. +=head2 kill_whole_group + + use Mojo::IOLoop::ReadWriteProcess; + my $process = Mojo::IOLoop::ReadWriteProcess->new(code => sub { setpgrp(0, 0); exec(...); }, kill_whole_group => 1 ); + $process->start(); + $process->send_signal(...); # Will skip the usual check whether $process->pid is running + $process->stop(); # Kills the entire process group and waits for all processes in the group to finish + +Defaults to C<0>, whether to send signals (e.g. to stop) to the entire process group. + +This is useful when the sub process creates further sub processes and creates a new process +group as shown in the example. In this case it might be useful to take care of the entire process +group when stopping and wait for every process in the group to finish. + =head2 collect_status Defaults to C<1>, If enabled it will automatically collect the status of the children process. diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/MANIFEST libmojo-ioloop-readwriteprocess-perl-0.27/MANIFEST --- libmojo-ioloop-readwriteprocess-perl-0.25/MANIFEST 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/MANIFEST 2020-07-03 00:27:21.000000000 +0000 @@ -51,6 +51,7 @@ t/12_mocked_container.t t/13_shared.t t/data/process_check.sh +t/data/simple_fork.pl t/data/subreaper/child.sh t/data/subreaper/dead_child.sh t/data/subreaper/dead_master.sh diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/META.json libmojo-ioloop-readwriteprocess-perl-0.27/META.json --- libmojo-ioloop-readwriteprocess-perl-0.25/META.json 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/META.json 2020-07-03 00:27:21.000000000 +0000 @@ -4,7 +4,7 @@ "Ettore Di Giacinto " ], "dynamic_config" : 0, - "generated_by" : "Minilla/v3.1.2", + "generated_by" : "Minilla/v3.1.10", "license" : [ "perl_5" ], @@ -29,14 +29,14 @@ "configure" : { "requires" : { "Module::Build" : "0.4005", - "perl" : "5.008_001" + "perl" : "5.016" } }, "develop" : { "requires" : { "Test::CPAN::Meta" : "0", "Test::MinimumVersion::Fast" : "0.04", - "Test::PAUSE::Permissions" : "0.04", + "Test::PAUSE::Permissions" : "0.07", "Test::Pod" : "1.41", "Test::Spellunker" : "v0.2.7" } @@ -56,7 +56,7 @@ "provides" : { "Mojo::IOLoop::ReadWriteProcess" : { "file" : "lib/Mojo/IOLoop/ReadWriteProcess.pm", - "version" : "0.25" + "version" : "0.27" }, "Mojo::IOLoop::ReadWriteProcess::CGroup" : { "file" : "lib/Mojo/IOLoop/ReadWriteProcess/CGroup.pm" @@ -148,16 +148,17 @@ "web" : "https://github.com/mudler/Mojo-IOLoop-ReadWriteProcess" } }, - "version" : "0.25", + "version" : "0.27", "x_contributors" : [ "Clemens Famulla-Conrad ", "Ettore Di Giacinto ", "Ettore Di Giacinto ", + "Marius Kittler ", "Mohammad S Anwar ", "Oliver Kurz ", "Santiago Zarate ", + "Santiago Zarate ", "Sebastian Riedel " ], - "x_serialization_backend" : "JSON::PP version 2.97001", "x_static_install" : 0 } diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/META.yml libmojo-ioloop-readwriteprocess-perl-0.27/META.yml --- libmojo-ioloop-readwriteprocess-perl-0.25/META.yml 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/META.yml 2020-07-03 00:27:21.000000000 +0000 @@ -6,9 +6,9 @@ Test::More: '0.98' configure_requires: Module::Build: '0.4005' - perl: 5.008_001 + perl: '5.016' dynamic_config: 0 -generated_by: 'Minilla/v3.1.2, CPAN::Meta::Converter version 2.150010' +generated_by: 'Minilla/v3.1.10, CPAN::Meta::Converter version 2.143240' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -27,7 +27,7 @@ provides: Mojo::IOLoop::ReadWriteProcess: file: lib/Mojo/IOLoop/ReadWriteProcess.pm - version: '0.25' + version: '0.27' Mojo::IOLoop::ReadWriteProcess::CGroup: file: lib/Mojo/IOLoop/ReadWriteProcess/CGroup.pm Mojo::IOLoop::ReadWriteProcess::CGroup::v1: @@ -87,14 +87,15 @@ bugtracker: https://github.com/mudler/Mojo-IOLoop-ReadWriteProcess/issues homepage: https://github.com/mudler/Mojo-IOLoop-ReadWriteProcess repository: git://github.com/mudler/Mojo-IOLoop-ReadWriteProcess.git -version: '0.25' +version: '0.27' x_contributors: - 'Clemens Famulla-Conrad ' - 'Ettore Di Giacinto ' - 'Ettore Di Giacinto ' + - 'Marius Kittler ' - 'Mohammad S Anwar ' - 'Oliver Kurz ' - 'Santiago Zarate ' + - 'Santiago Zarate ' - 'Sebastian Riedel ' -x_serialization_backend: 'CPAN::Meta::YAML version 0.018' x_static_install: 0 diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/README.md libmojo-ioloop-readwriteprocess-perl-0.27/README.md --- libmojo-ioloop-readwriteprocess-perl-0.25/README.md 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/README.md 2020-07-03 00:27:21.000000000 +0000 @@ -53,7 +53,7 @@ # EVENTS -[Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess) inherits all events from [Mojo::EventEmitter](https://metacpan.org/pod/Mojo::EventEmitter) and can emit +[Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess) inherits all events from [Mojo::EventEmitter](https://metacpan.org/pod/Mojo%3A%3AEventEmitter) and can emit the following new ones. ## start @@ -134,7 +134,7 @@ # ATTRIBUTES -[Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess) inherits all attributes from [Mojo::EventEmitter](https://metacpan.org/pod/Mojo::EventEmitter) and implements +[Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess) inherits all attributes from [Mojo::EventEmitter](https://metacpan.org/pod/Mojo%3A%3AEventEmitter) and implements the following new ones. ## execute @@ -203,7 +203,7 @@ my $session = $process->session; $session->enable_subreaper; -Returns the current [Mojo::IOLoop::ReadWriteProcess::Session](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess::Session) singleton. +Returns the current [Mojo::IOLoop::ReadWriteProcess::Session](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess%3A%3ASession) singleton. ## subreaper @@ -224,7 +224,7 @@ my $loop = $process->ioloop; $subprocess = $process->ioloop(Mojo::IOLoop->new); -Event loop object to control, defaults to the global [Mojo::IOLoop](https://metacpan.org/pod/Mojo::IOLoop) singleton. +Event loop object to control, defaults to the global [Mojo::IOLoop](https://metacpan.org/pod/Mojo%3A%3AIOLoop) singleton. ## max\_kill\_attempts @@ -239,6 +239,20 @@ It can be used with blocking\_stop, so if the number of attempts are exhausted, a SIGKILL and waitpid will be tried at the end. +## kill\_whole\_group + + use Mojo::IOLoop::ReadWriteProcess; + my $process = Mojo::IOLoop::ReadWriteProcess->new(code => sub { setpgrp(0, 0); exec(...); }, kill_whole_group => 1 ); + $process->start(); + $process->send_signal(...); # Will skip the usual check whether $process->pid is running + $process->stop(); # Kills the entire process group and waits for all processes in the group to finish + +Defaults to `0`, whether to send signals (e.g. to stop) to the entire process group. + +This is useful when the sub process creates further sub processes and creates a new process +group as shown in the example. In this case it might be useful to take care of the entire process +group when stopping and wait for every process in the group to finish. + ## collect\_status Defaults to `1`, If enabled it will automatically collect the status of the children process. @@ -278,12 +292,12 @@ ## error -Returns a [Mojo::Collection](https://metacpan.org/pod/Mojo::Collection) of errors. +Returns a [Mojo::Collection](https://metacpan.org/pod/Mojo%3A%3ACollection) of errors. Note: errors that can be captured only at the end of the process # METHODS -[Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess) inherits all methods from [Mojo::EventEmitter](https://metacpan.org/pod/Mojo::EventEmitter) and implements +[Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess) inherits all methods from [Mojo::EventEmitter](https://metacpan.org/pod/Mojo%3A%3AEventEmitter) and implements the following new ones. ## start() @@ -418,7 +432,7 @@ Mojo::IOLoop->singleton->start() unless Mojo::IOLoop->singleton->is_running; -Returns a [Mojo::IOLoop::Stream](https://metacpan.org/pod/Mojo::IOLoop::Stream) object and demand the wait operation to [Mojo::IOLoop](https://metacpan.org/pod/Mojo::IOLoop). +Returns a [Mojo::IOLoop::Stream](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AStream) object and demand the wait operation to [Mojo::IOLoop](https://metacpan.org/pod/Mojo%3A%3AIOLoop). It needs `set_pipes` enabled. Default IOLoop can be overridden in `ioloop()`. ## wait() @@ -578,9 +592,9 @@ $pool->on( stop => sub { print "Process: ".(+shift()->pid)." finished"; } ); $pool->stop(); -Returns a [Mojo::IOLoop::ReadWriteProcess::Pool](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess::Pool) object that represent a group of processes. +Returns a [Mojo::IOLoop::ReadWriteProcess::Pool](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess%3A%3APool) object that represent a group of processes. -It accepts the same arguments as [Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess), and the last one represent the number of processes to generate. +It accepts the same arguments as [Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess), and the last one represent the number of processes to generate. ## batch() @@ -589,8 +603,8 @@ $pool->add(sub { print "Hello\n" }); $pool->on(stop => sub { shift->_diag("Done!") })->start->wait_stop; -Returns a [Mojo::IOLoop::ReadWriteProcess::Pool](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess::Pool) object generated from supplied arguments. -It accepts as input the same parameter of [Mojo::IOLoop::ReadWriteProcess::Pool](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess::Pool) constructor ( see parallel() ). +Returns a [Mojo::IOLoop::ReadWriteProcess::Pool](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess%3A%3APool) object generated from supplied arguments. +It accepts as input the same parameter of [Mojo::IOLoop::ReadWriteProcess::Pool](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess%3A%3APool) constructor ( see parallel() ). ## process() @@ -602,9 +616,9 @@ process(sub { print "Hello\n" })->start->wait_stop; -Returns a [Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess) object that represent a process. +Returns a [Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess) object that represent a process. -It accepts the same arguments as [Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess). +It accepts the same arguments as [Mojo::IOLoop::ReadWriteProcess](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess). ## queue() @@ -613,7 +627,7 @@ $q->add(sub { return 42 } ); $q->consume; -Returns a [Mojo::IOLoop::ReadWriteProcess::Queue](https://metacpan.org/pod/Mojo::IOLoop::ReadWriteProcess::Queue) object that represent a queue. +Returns a [Mojo::IOLoop::ReadWriteProcess::Queue](https://metacpan.org/pod/Mojo%3A%3AIOLoop%3A%3AReadWriteProcess%3A%3AQueue) object that represent a queue. # DEBUGGING diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/t/01_run.t libmojo-ioloop-readwriteprocess-perl-0.27/t/01_run.t --- libmojo-ioloop-readwriteprocess-perl-0.25/t/01_run.t 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/t/01_run.t 2020-07-03 00:27:21.000000000 +0000 @@ -37,7 +37,10 @@ like $@, qr/Nothing to do/, "Process with no code nor execute command, will fail"; - $p = Mojo::IOLoop::ReadWriteProcess->new(); + $p = Mojo::IOLoop::ReadWriteProcess->new( + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01 + ); eval { $p->_fork(); }; ok $@, "Error expected"; like $@, qr/Can't spawn child without code/, "_fork() with no code will fail"; @@ -47,7 +50,9 @@ pipe(PARENT, CHILD); my $p = Mojo::IOLoop::ReadWriteProcess->new( - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + code => sub { close(PARENT); open STDERR, ">&", \*CHILD or die $!; print STDERR "FOOBARFTW\n" while 1; @@ -67,7 +72,9 @@ pipe(PARENT, CHILD); my $p = Mojo::IOLoop::ReadWriteProcess->new( - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + code => sub { close(PARENT); open STDERR, ">&", \*CHILD or die $!; print STDERR "FOOBARFTW\n"; @@ -133,9 +140,12 @@ "You do not seem to have $test_script_sigtrap. The script is required to run the test" unless -e $test_script_sigtrap; use Mojo::IOLoop::ReadWriteProcess; - my $p = Mojo::IOLoop::ReadWriteProcess->new(execute => $test_script)->start(); - is $p->getline, "TEST normal print\n", 'Get right output from stdout'; - is $p->err_getline, "TEST error print\n", 'Get right output from stderr'; + my $p = Mojo::IOLoop::ReadWriteProcess->new( + sleeptime_during_kill => 0.1, + execute => $test_script + )->start(); + is $p->getline, "TEST normal print\n", 'Get right output from stdout'; + is $p->err_getline, "TEST error print\n", 'Get right output from stderr'; is $p->is_running, 1, 'process is still waiting for our input'; $p->write("FOOBAR"); is $p->read, "you entered FOOBAR\n", @@ -144,13 +154,15 @@ is $p->is_running, 0, 'process is not running anymore'; $p = Mojo::IOLoop::ReadWriteProcess->new( - execute => $test_script, - args => [ + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + execute => $test_script, + args => [ qw(FOO BAZ) ])->start(); - is $p->stdout, "TEST normal print\n", 'Get right output from stdout'; - is $p->err_getline, "TEST error print\n", 'Get right output from stderr'; + is $p->stdout, "TEST normal print\n", 'Get right output from stdout'; + is $p->err_getline, "TEST error print\n", 'Get right output from stderr'; is $p->is_running, 1, 'process is still waiting for our input'; $p->write("FOOBAR"); is $p->getline, "you entered FOOBAR\n", @@ -160,10 +172,12 @@ is $p->getline, "FOO BAZ\n", 'process received extra arguments'; is $p->exit_status, 100, 'able to retrieve function return'; - $p = Mojo::IOLoop::ReadWriteProcess->new(execute => $test_script) - ->args([qw(FOO BAZ)])->start(); - is $p->stdout, "TEST normal print\n", 'Get right output from stdout'; - is $p->err_getline, "TEST error print\n", 'Get right output from stderr'; + $p = Mojo::IOLoop::ReadWriteProcess->new( + sleeptime_during_kill => 0.1, + execute => $test_script + )->args([qw(FOO BAZ)])->start(); + is $p->stdout, "TEST normal print\n", 'Get right output from stdout'; + is $p->err_getline, "TEST error print\n", 'Get right output from stderr'; is $p->is_running, 1, 'process is still waiting for our input'; $p->write("FOOBAR"); is $p->getline, "you entered FOOBAR\n", @@ -174,8 +188,10 @@ is $p->exit_status, 100, 'able to retrieve function return'; $p = Mojo::IOLoop::ReadWriteProcess->new( - separate_err => 0, - execute => $test_script + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + separate_err => 0, + execute => $test_script ); $p->start(); is $p->is_running, 1, 'process is still running'; @@ -186,9 +202,11 @@ 'Still able to get stdout output, always in getline()'; my $p2 = Mojo::IOLoop::ReadWriteProcess->new( - separate_err => 0, - execute => $test_script, - set_pipes => 0 + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + separate_err => 0, + execute => $test_script, + set_pipes => 0 ); $p2->start(); is $p2->getline, undef, "pipes are correctly disabled"; @@ -197,17 +215,19 @@ 'take exit status even with set_pipes = 0 (we killed it)'; $p = Mojo::IOLoop::ReadWriteProcess->new( - verbose => 1, - separate_err => 0, - execute => $test_script_sigtrap, - max_kill_attempts => -4 + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + verbose => 1, + separate_err => 0, + execute => $test_script_sigtrap, + max_kill_attempts => -4, ); # ;) $p->start(); $p->stop(); is $p->is_running, 1, 'process is still running'; my $err = ${(@{$p->error})[0]}; my $exp = qr/Could not kill process/; - like $err, $exp , 'Error is not empty if process could not be killed'; + like $err, $exp, 'Error is not empty if process could not be killed'; $p->max_kill_attempts(50); $p->blocking_stop(0); $p->stop(); @@ -221,11 +241,13 @@ $p = Mojo::IOLoop::ReadWriteProcess->new( - verbose => 1, - separate_err => 0, - blocking_stop => 1, - execute => $test_script, - max_kill_attempts => -1 # ;) + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + verbose => 1, + separate_err => 0, + blocking_stop => 1, + execute => $test_script, + max_kill_attempts => -1 # ;) )->start()->stop(); is $p->is_running, 0, @@ -233,12 +255,14 @@ my $pidfile = tempfile; $p = Mojo::IOLoop::ReadWriteProcess->new( - verbose => 1, - separate_err => 0, - blocking_stop => 1, - execute => $test_script, - max_kill_attempts => -1, # ;) - pidfile => $pidfile + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + verbose => 1, + separate_err => 0, + blocking_stop => 1, + execute => $test_script, + max_kill_attempts => -1, # ;) + pidfile => $pidfile )->start(); my $pid = path($pidfile)->slurp(); is -e $pidfile, 1, 'Pidfile is there!'; @@ -248,11 +272,13 @@ $pidfile = tempfile; $p = Mojo::IOLoop::ReadWriteProcess->new( - verbose => 1, - separate_err => 0, - blocking_stop => 1, - execute => $test_script, - max_kill_attempts => -1, # ;) + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + verbose => 1, + separate_err => 0, + blocking_stop => 1, + execute => $test_script, + max_kill_attempts => -1, # ;) )->start(); $p->write_pidfile($pidfile); $pid = path($pidfile)->slurp(); @@ -262,11 +288,13 @@ is -e $pidfile, undef, 'Pidfile got removed after stop()'; $p = Mojo::IOLoop::ReadWriteProcess->new( - verbose => 1, - separate_err => 0, - blocking_stop => 1, - execute => $test_script, - max_kill_attempts => -1, # ;) + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + verbose => 1, + separate_err => 0, + blocking_stop => 1, + execute => $test_script, + max_kill_attempts => -1, # ;) )->start(); is $p->write_pidfile(), undef, "No filename given to write_pidfile"; $p->stop(); @@ -276,7 +304,9 @@ use Mojo::IOLoop::ReadWriteProcess; use IO::Select; my $p = Mojo::IOLoop::ReadWriteProcess->new( - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + code => sub { my ($self) = shift; my $parent_output = $self->channel_out; my $parent_input = $self->channel_in; @@ -329,8 +359,10 @@ is $p->is_running, 0, 'process is not running'; $p = Mojo::IOLoop::ReadWriteProcess->new( - separate_err => 0, - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + separate_err => 0, + code => sub { my ($self) = shift; my $parent_output = $self->channel_out; my $parent_input = $self->channel_in; @@ -345,7 +377,8 @@ is $p->is_running, 0, 'process is not running'; is $p->return_status, 256, 'right return code'; - $p = Mojo::IOLoop::ReadWriteProcess->new(sub { die "Fatal error"; }); + $p = Mojo::IOLoop::ReadWriteProcess->new(sub { die "Fatal error"; }, + sleeptime_during_kill => 0.1); my $event_fired = 0; $p->on( process_error => sub { @@ -361,16 +394,24 @@ like(${(@{$p->error})[0]}, qr/Fatal error/, 'right error'); is $event_fired, 1, 'error event fired'; - $p = Mojo::IOLoop::ReadWriteProcess->new(sub { return 42 }, - internal_pipes => 0); + $p = Mojo::IOLoop::ReadWriteProcess->new( + sub { return 42 }, + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + internal_pipes => 0 + ); $p->start(); $p->wait_stop(); is $p->is_running, 0, 'process is not running'; is $p->return_status, undef, 'process did not return nothing when internal_pipes are disabled'; - $p = Mojo::IOLoop::ReadWriteProcess->new(sub { die "Bah" }, - internal_pipes => 0); + $p = Mojo::IOLoop::ReadWriteProcess->new( + sub { die "Bah" }, + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + internal_pipes => 0 + ); $p->start(); $p->wait_stop(); is $p->is_running, 0, 'process is not running'; @@ -379,9 +420,11 @@ # XXX: flaky test temporarly skip it. is !!$p->exit_status, 1, 'Exit status is there'; $p = Mojo::IOLoop::ReadWriteProcess->new( - separate_err => 0, - set_pipes => 0, - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + separate_err => 0, + set_pipes => 0, + code => sub { print "TEST normal print\n"; print STDERR "TEST error print\n"; return "256"; @@ -392,17 +435,21 @@ is $p->return_status, 256, "grab exit_status even if no pipes are set"; $p = Mojo::IOLoop::ReadWriteProcess->new( - separate_err => 0, - set_pipes => 1, - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + separate_err => 0, + set_pipes => 1, + code => sub { exit 100; })->start(); $p->wait_stop(); is $p->exit_status, 100, "grab exit_status even if no pipes are set"; $p = Mojo::IOLoop::ReadWriteProcess->new( - separate_err => 0, - code => sub { + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + separate_err => 0, + code => sub { print STDERR "TEST error print\n" for (1 .. 6); my $a = ; })->start(); @@ -412,7 +459,46 @@ $p->write("a"); $p->wait_stop(); like $p->stderr_all, qr/TEST error print/, 'read all from stderr works'; - is $p->read_all, '', 'stdout is empty'; + is $p->read_all, '', 'stdout is empty'; +}; + +subtest stop_whole_process_group_gracefully => sub { + my $test_script = "$FindBin::Bin/data/simple_fork.pl"; + plan skip_all => + "You do not seem to have $test_script which is required to run the test" + unless -e $test_script; + + # run the "term_trap.pl" script and its sub processes within its own + # process group + # notes: - Not using "term_trap.sh" here because bash interferes with the + # process group. + # - Set TOTAL_SLEEPTIME_DURING_KILL to a notable number of seconds + # to check whether the sub processes would actually be granted + # this number of seconds before getting killed. This is not set by + # default to avoid slowing down the CI. + my $sub_process = Mojo::IOLoop::ReadWriteProcess->new( + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + max_kill_attempts => 1, + separate_err => 0, + blocking_stop => 1, + kill_whole_group => 1, + total_sleeptime_during_kill => $ENV{TOTAL_SLEEPTIME_DURING_KILL} // 0.05, + code => sub { + $SIG{TERM} = 'IGNORE'; + setpgrp(0, 0); + exec(perl => $test_script); + })->start(); + + # wait until the sub process changes its process group + # note: Otherwise it still has the process group of this unit test and calling + # stop would also stop the test itself. + my $test_gpid = getpgrp(0); + my $sub_process_pid = $sub_process->pid; + sleep 0.1 while $test_gpid == getpgrp($sub_process_pid); + + $sub_process->stop(); + is $sub_process->is_running, 0, 'process is shut down via kill_whole_group'; }; subtest process_debug => sub { @@ -425,7 +511,11 @@ local *STDERR = $handle; delete $INC{'Mojo/IOLoop/ReadWriteProcess.pm'}; eval "no warnings; require Mojo::IOLoop::ReadWriteProcess"; ## no critic - Mojo::IOLoop::ReadWriteProcess->new(sub { 1; })->start()->stop(); + Mojo::IOLoop::ReadWriteProcess->new( + code => sub { 1; }, + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01 + )->start()->stop(); } like $buffer, qr/Fork: \{/, @@ -439,7 +529,10 @@ delete $INC{'Mojo/IOLoop/ReadWriteProcess.pm'}; eval "no warnings; require Mojo::IOLoop::ReadWriteProcess"; ## no critic Mojo::IOLoop::ReadWriteProcess->new( - execute => "$FindBin::Bin/data/process_check.sh")->start()->stop(); + execute => "$FindBin::Bin/data/process_check.sh", + kill_sleeptime => 0.01, + sleeptime_during_kill => 0.01, + )->start()->stop(); } like $buffer, qr/Execute: .*process_check.sh/, diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/t/03_func.t libmojo-ioloop-readwriteprocess-perl-0.27/t/03_func.t --- libmojo-ioloop-readwriteprocess-perl-0.25/t/03_func.t 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/t/03_func.t 2020-07-03 00:27:21.000000000 +0000 @@ -23,7 +23,7 @@ subtest write_pidfile => sub { use Mojo::File 'tempfile'; my $pidfile = tempfile; - my $p = process(code => sub { exit 0 }, pidfile => $pidfile); + my $p = process(code => sub { exit 0 }, pidfile => $pidfile); $p->write_pidfile; ok !$pidfile->slurp; }; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/t/11_containers.t libmojo-ioloop-readwriteprocess-perl-0.27/t/11_containers.t --- libmojo-ioloop-readwriteprocess-perl-0.25/t/11_containers.t 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/t/11_containers.t 2020-07-03 00:27:21.000000000 +0000 @@ -136,7 +136,7 @@ my @pids; my $fired; - $c->session->on(register => sub { push(@pids, shift) }); + $c->session->on(register => sub { push(@pids, shift) }); $c->process->on(collected => sub { $fired++ }); $c->once(stop => sub { $fired++ }); diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/t/13_shared.t libmojo-ioloop-readwriteprocess-perl-0.27/t/13_shared.t --- libmojo-ioloop-readwriteprocess-perl-0.25/t/13_shared.t 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/t/13_shared.t 2020-07-03 00:27:21.000000000 +0000 @@ -51,7 +51,7 @@ process( sub { my $sem = semaphore(key => $sem_key); - my $e = 1; + my $e = 1; if ($sem->acquire({wait => 1, undo => 0})) { $e = 0; $sem->release(); @@ -150,7 +150,7 @@ subtest 'concurrent memory read/write' => sub { use IPC::SysV 'ftok'; - my $k = ftok($0, 0); + my $k = ftok($0, 0); my $mem = shared_memory(key => $k); $mem->_lock->remove; my $default = shared_memory; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/t/data/simple_fork.pl libmojo-ioloop-readwriteprocess-perl-0.27/t/data/simple_fork.pl --- libmojo-ioloop-readwriteprocess-perl-0.25/t/data/simple_fork.pl 1970-01-01 00:00:00.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/t/data/simple_fork.pl 2020-07-03 00:27:21.000000000 +0000 @@ -0,0 +1,15 @@ +use warnings; +use strict; + +my $pid1 = fork(); +if ($pid1 == 0) { + print "fork 1\n"; + sleep 1000; +} +my $pid2 = fork(); +if ($pid2 == 0) { + print "fork 2\n"; + sleep 1000; +} +waitpid $pid1, 0; +waitpid $pid2, 0; diff -Nru libmojo-ioloop-readwriteprocess-perl-0.25/t/lib/Mojo/IOLoop/ReadWriteProcess/Test/Utils.pm libmojo-ioloop-readwriteprocess-perl-0.27/t/lib/Mojo/IOLoop/ReadWriteProcess/Test/Utils.pm --- libmojo-ioloop-readwriteprocess-perl-0.25/t/lib/Mojo/IOLoop/ReadWriteProcess/Test/Utils.pm 2020-04-08 14:51:25.000000000 +0000 +++ libmojo-ioloop-readwriteprocess-perl-0.27/t/lib/Mojo/IOLoop/ReadWriteProcess/Test/Utils.pm 2020-07-03 00:27:21.000000000 +0000 @@ -15,7 +15,7 @@ sleep 1; $attempts++; } - $or->() if $or && !$condition->(); + $or->() if $or && !$condition->(); warn "Attempts terminated!" if DEBUG; }