.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Mojo::IOLoop::ReadWriteProcess::Container 3pm" .TH Mojo::IOLoop::ReadWriteProcess::Container 3pm "2019-01-06" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mojo::IOLoop::ReadWriteProcess::Container \- (kinda) Pure Perl containers. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $container = container( \& pid_isolation => 1, # Best\-effort, as depends on where you run it (you need CAP_SYS_ADMIN) \& subreaper => 1, \& group => "my_org", \& name => "my_process", \& process => process( \& sub { \& # Exec, fork .. \& process(sub { warn "\eo/"; sleep 42; })\->start; \& process(sub { warn "\eo/"; sleep 42; })\->start; \& process( \& sub { \& process( \& sub { \& process(sub { warn "\eo/"; sleep 42; })\->start; \& warn "\eo/"; \& sleep 400; \& warn "\eo/"; \& })\->start; \& warn "Hey"; \& sleep 42; \& warn "\eo/"; \& })\->start; \& sleep 42; \& } \& )\->separate_err(0)); \& \& $container\->start(); \& $container\->is_running; \& $container\->stop; \& \& my @procs = $container\->cgroups\->first\->processes; \& $container\->cgroups\->first\->pid\->max(300); \& \& $container\->process\->on(stop => sub { print "Main container process stopped!" }); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Mojo::IOLoop::ReadWriteProcess::Container ties anonymous functions or a Mojo::IOLoop::ReadWriteProcess object to differents sets of Mojo::IOLoop::ReadWriteProcess::CGroup implementations. .PP When the \f(CW\*(C`pid_isolation\*(C'\fR attribute is set, it needs special permissions (\s-1CAP_SYS_ADMIN\s0 capabilities). This module uses features that are only available on Linux, and requires cgroups and capability (\s-1CAP_SYS_ADMIN\s0) for unshare syscalls to achieve pid isolation. .SH "EVENTS" .IX Header "EVENTS" Mojo::IOLoop::ReadWriteProcess inherits all events from Mojo::EventEmitter and can emit the following new ones. .SS "start" .IX Subsection "start" .Vb 4 \& $container\->on(start => sub { \& my ($process) = @_; \& ... \& }); .Ve .PP Emitted when the container starts. .SS "stop" .IX Subsection "stop" .Vb 4 \& $container\->on(stop => sub { \& my ($container) = @_; \& ... \& }); .Ve .PP Emitted when the container stops. .SS "process_error" .IX Subsection "process_error" .Vb 4 \& $container\->on(container_error => sub { \& my ($e) = @_; \& my @errors = @{$e}; \& }); .Ve .PP Emitted when the container produce errors. .SH "METHODS" .IX Header "METHODS" Mojo::IOLoop::ReadWriteProcess::Container inherits all methods from Mojo::EventEmitter and implements the following new ones. .SS "start" .IX Subsection "start" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container( name=>"test", process => sub { print "Hello!" }); \& $c\->start(); .Ve .PP Starts the container, it's main process is a Mojo::IOLoop::ReadWriteProcess, contained in the \f(CW\*(C`process()\*(C'\fR attribute. On stop it will terminate every process included in the cgroups attribute. .SS "is_running" .IX Subsection "is_running" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container( name=>"test", process => sub { print "Hello!" }); \& $c\->is_running(); .Ve .PP Returns 1 if the container is running. .SS "stop" .IX Subsection "stop" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container( name=>"test", process => sub { print "Hello!" })\->start; \& $c\->stop(); .Ve .PP Stops the container and kill all the processes belonging to the cgroup. It also registers all the unknown processes to the current Mojo::IOLoop::ReadWriteProcess::Session. .SS "wait_stop" .IX Subsection "wait_stop" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container( name=>"test", process => sub { print "Hello!" })\->start; \& $c\->wait_stop(); .Ve .PP Wait before stopping the container. .SS "wait" .IX Subsection "wait" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container( name=>"test", process => sub { print "Hello!" })\->start; \& $c\->wait(); .Ve .PP Wait the container to stop .SS "migrate_process" .IX Subsection "migrate_process" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container( name=>"test", process => sub { print "Hello!" })\->start; \& $c\->migrate_process(42); .Ve .PP Migrate the given process to the container cgroup. .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" Mojo::IOLoop::ReadWriteProcess::Container inherits all attributes from Mojo::EventEmitter and implements the following new ones. .SS "name" .IX Subsection "name" .Vb 4 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& use Mojo::IOLoop::ReadWriteProcess::CGroup qw(cgroupv1); \& use Mojo::Collection \*(Aqc\*(Aq; \& \& my $container = container( name => "test", process => sub { print "Hello!" } ); \& \& $container\->session\->on(register => sub { ... }); \& $container\->start(); .Ve .PP Sets the container name. It creates in the indicated (or default) cgroups a sub-tree with the container name. .PP This means that cgroups settings can be done also outside of the container object: .PP .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::CGroup qw(cgroupv1); \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& \& my $container = container( name => "test", process => sub { print "Hello!" } ); \& \& cgroupv1\->from($continer\->cgroups\->first\->_group)\->pid\->max(100); .Ve .PP As cgroups are represented by path, you can set options directly from controllers objects that are pointing to the same cgroup slice. .SS "group" .IX Subsection "group" .Vb 4 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& use Mojo::IOLoop::ReadWriteProcess::CGroup qw(cgroupv2); \& use Mojo::Collection \*(Aqc\*(Aq; \& \& my $container = container( name => "bar", group => "foo", process => sub { print "Hello!" } ); \& my $container2 = container( name => "bar2", group => "foo", process => sub { print "Hello!" } ); \& \& $container\->start(); \& $container2\->start(); \& \& my $group_cgroup = cgroupv2\->from($container2\->cgroups\->first\->parent); \& \& $group_cgroup\->pid\->max(200); .Ve .PP Sets the container group. If containers are sharing the same group they will inherit the same CGroup parent path, in such way it is possible to create controllers pointing to it and set specific options for the whole group. .SS "pid_isolation" .IX Subsection "pid_isolation" .Vb 4 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& use Mojo::IOLoop::ReadWriteProcess::CGroup qw(cgroupv1); \& use Mojo::Collection \*(Aqc\*(Aq; \& \& my $container = container( pid_isolation => 1, process => sub { print "Hello!" } ); \& \& $container\->session\->on(register => sub { ... }); \& $container\->start(); .Ve .PP If set, the process will see itself as \s-1PID 1.\s0 It needs \s-1CAP_SYS_ADMIN\s0 capabilities set on the executable (or run as root). .SS "pre_migrate" .IX Subsection "pre_migrate" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $container = container( pre_migrate => 1, process => sub { print "Hello!" } ); \& \& $container\->session\->on(register => sub { ... }); \& $container\->start(); .Ve .PP If set, the process will migrate itself into the cgroup. .SS "clean_cgroup" .IX Subsection "clean_cgroup" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $container = container( clean_cgroup => 1, process => sub { print "Hello!" }); \& \& $container\->session\->on(register => sub { ... }); \& $container\->start(); .Ve .PP If set, attempts to destroy the cgroup after the process terminated its execution. .SS "subreaper" .IX Subsection "subreaper" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container(subreaper => 1, name=>"test", process => sub { print "Hello!" }); \& $c\->start(); .Ve .PP Enable subreaper mode inside the child process. .SS "process" .IX Subsection "process" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container(process => sub { print "Hello!" }); \& my $c = container(process => sub { print "Hello!" }); \& \& $c\->start(); .Ve .PP The process to run. It can be an anonymous function or a Mojo::IOLoop::ReadWriteProcess object. .SS "namespace" .IX Subsection "namespace" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container(process => sub { print "Hello!" }); \& $c\->namespace\->unshare(0); # All \& $c\->start(); .Ve .PP Set/Return Mojo::IOLoop::ReadWriteProcess::Namespace object. It's main use is to invoke syscalls. .SS "session" .IX Subsection "session" .Vb 2 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& \& my $c = container(process => process(sub { print "Hello!" })); \& $c\->session\->on(register => sub { ... }); \& $c\->start(); .Ve .PP Returns/Set the Mojo::IOLoop::ReadWriteProcess::Session singleton object. .SS "unshare" .IX Subsection "unshare" .Vb 3 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& use Mojo::IOLoop::ReadWriteProcess::Namespace qw( CLONE_NEWPID CLONE_NEWNS ); \& \& my $c = container( unshare=> CLONE_NEWPID | CLONE_NEWNS, process => sub { print "Hello!" } ); \& $c\->session\->on(register => sub { ... }); \& $c\->start(); .Ve .PP Returns/Set the unshare syscall options. See man \fBunshare\fR\|(2) for further documentation. .SS "cgroups" .IX Subsection "cgroups" .Vb 4 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& use Mojo::IOLoop::ReadWriteProcess::CGroup qw(cgroupv1); \& use Mojo::Collection \*(Aqc\*(Aq; \& \& my $container = container(process => sub { print "Hello!" }); \& $container\->cgroups( c(cgroupv1(controller => \*(Aqpids\*(Aq), cgroupv1(controller => \*(Aqmemory\*(Aq)) ); \& \& $container\->session\->on(register => sub { ... }); \& $container\->start(); .Ve .PP Returns/Set a Mojo::Collection collection of CGroups where the process should belong to. If used with a single CGroup, you don't need to pass the Mojo::Collection object: .PP .Vb 4 \& use Mojo::IOLoop::ReadWriteProcess::Container qw(container); \& use Mojo::IOLoop::ReadWriteProcess qw(process); \& use Mojo::IOLoop::ReadWriteProcess::CGroup qw(cgroupv1); \& use Mojo::Collection \*(Aqc\*(Aq; \& \& my $container = container(cgroups=> cgroupv1(controller => \*(Aqpids\*(Aq), process => sub { print "Hello!" }); \& \& $container\->session\->on(register => sub { ... }); \& $container\->start(); .Ve .SH "DEBUGGING" .IX Header "DEBUGGING" You can set the \s-1MOJO_EVENTEMITTER_DEBUG\s0 environment variable to get some advanced diagnostics information printed to \s-1STDERR.\s0 .PP .Vb 1 \& MOJO_EVENTEMITTER_DEBUG=1 .Ve .PP Also, you can set \s-1MOJO_PROCESS_DEBUG\s0 environment variable to get diagnostics about the process execution. .PP .Vb 1 \& MOJO_PROCESS_DEBUG=1 .Ve .SH "LICENSE" .IX Header "LICENSE" Copyright (C) Ettore Di Giacinto. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "AUTHOR" .IX Header "AUTHOR" Ettore Di Giacinto