line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Proc::FastSpawn - fork+exec, or spawn, a subprocess as quickly as possible |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Proc::FastSpawn; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# simple use |
10
|
|
|
|
|
|
|
my $pid = spawn "/bin/echo", ["echo", "hello, world"]; |
11
|
|
|
|
|
|
|
... |
12
|
|
|
|
|
|
|
waitpid $pid, 0; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# with environment |
15
|
|
|
|
|
|
|
my $pid = spawn "/bin/echo", ["echo", "hello, world"], ["PATH=/bin", "HOME=/tmp"]; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# inheriting file descriptors |
18
|
|
|
|
|
|
|
pipe R, W or die; |
19
|
|
|
|
|
|
|
fd_inherit fileno W; |
20
|
|
|
|
|
|
|
my $pid = spawn "/bin/sh", ["sh", "-c", "echo a pipe >&" . fileno W]; |
21
|
|
|
|
|
|
|
close W; |
22
|
|
|
|
|
|
|
print ; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 DESCRIPTION |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
The purpose of this small (in scope and footprint) module is simple: |
27
|
|
|
|
|
|
|
spawn a subprocess asynchronously as efficiently and/or fast as |
28
|
|
|
|
|
|
|
possible. Basically the same as calling fork+exec (on POSIX), but |
29
|
|
|
|
|
|
|
hopefully faster than those two syscalls. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Apart from fork overhead, this module also allows you to fork+exec |
32
|
|
|
|
|
|
|
programs when otherwise you couldn't - for example, when you use POSIX |
33
|
|
|
|
|
|
|
threads in your perl process then it generally isn't safe to call |
34
|
|
|
|
|
|
|
fork from perl, but it is safe to use this module to execute external |
35
|
|
|
|
|
|
|
processes. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
If neither of these are problems for you, you can safely ignore this |
38
|
|
|
|
|
|
|
module. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
So when is fork+exec not fast enough, how can you do it faster, and why |
41
|
|
|
|
|
|
|
would it matter? |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Forking a process requires making a complete copy of a process. Even |
44
|
|
|
|
|
|
|
thought almost every implementation only copies page tables and not the |
45
|
|
|
|
|
|
|
memory itself, this is still not free. For example, on my 3.6GHz amd64 |
46
|
|
|
|
|
|
|
box, I can fork a 5GB process only twenty times a second. For a real-time |
47
|
|
|
|
|
|
|
process that must meet stricter deadlines, this is too slow. For a busy |
48
|
|
|
|
|
|
|
and big web server, starting CGI scripts might mean unacceptable overhead. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
A workaround is to use C - this function isn't very portable, but |
51
|
|
|
|
|
|
|
it avoids the memory copy that C has to do. Some systems have an |
52
|
|
|
|
|
|
|
optimised implementation of C, and some systems have nothing. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
This module tries to abstract these differences away. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
As for what improvements to expect - on the 3.6GHz amd64 box that this |
57
|
|
|
|
|
|
|
module was originally developed on, a 3MB perl process (basically just |
58
|
|
|
|
|
|
|
perl + Proc::FastSpawn) takes 3.6s to run /bin/true 10000 times using |
59
|
|
|
|
|
|
|
fork+exec, and only 2.6s when using vfork+exec. In a 22MB process, the |
60
|
|
|
|
|
|
|
difference is already 5.0s vs 2.6s, and so on. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 FUNCTIONS |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
All the following functions are currently exported by default. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=over 4 |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=cut |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
package Proc::FastSpawn; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# only used on WIN32 - maddeningly complex and doesn't even work |
73
|
|
|
|
|
|
|
sub _quote { |
74
|
|
|
|
|
|
|
$_[0] = [@{ $_[0] }]; # make copy |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
for (@{ $_[0] }) { |
77
|
|
|
|
|
|
|
if (/[\x01-\x20"]/) { # some sources say only space, "\t\n\v need to be escaped, microsoft says space and tab |
78
|
|
|
|
|
|
|
s/(\\*)"/$1$1\\"/g; # double + extra escape before " |
79
|
|
|
|
|
|
|
s/(\\+)$/$1$1/; # just double at end |
80
|
|
|
|
|
|
|
$_ = '"' . $_ . '"'; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
BEGIN { |
86
|
3
|
|
|
3
|
|
2947
|
$VERSION = '1.2'; |
87
|
|
|
|
|
|
|
|
88
|
3
|
|
|
|
|
42
|
our @ISA = qw(Exporter); |
89
|
3
|
|
|
|
|
9
|
our @EXPORT = qw(spawn spawnp fd_inherit); |
90
|
3
|
|
|
|
|
17
|
require Exporter; |
91
|
|
|
|
|
|
|
|
92
|
3
|
|
|
|
|
12
|
require XSLoader; |
93
|
3
|
|
|
|
|
1817
|
XSLoader::load (__PACKAGE__, $VERSION); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=item $pid = spawn $path, \@argv[, \@envp] |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Creates a new process and tries to make it execute C<$path>, with the given |
99
|
|
|
|
|
|
|
arguments and optionally the given environment variables, similar to |
100
|
|
|
|
|
|
|
calling fork + execv, or execve. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Returns the PID of the new process if successful. On any error, C |
103
|
|
|
|
|
|
|
is currently returned. Failure to execution might or might not be reported |
104
|
|
|
|
|
|
|
as C, or via a subprocess exit status of C<127>. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item $pid = spawnp $file, \@argv[, \@envp] |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Like C, but searches C<$file> in C<$ENV{PATH}> like the shell would |
109
|
|
|
|
|
|
|
do. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=item fd_inherit $fileno[, $on] |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
File descriptors can be inherited by the spawned processes or not. This is |
114
|
|
|
|
|
|
|
decided on a per file descriptor basis. This module does nothing to any |
115
|
|
|
|
|
|
|
preexisting handles, but with this call, you can change the state of a |
116
|
|
|
|
|
|
|
single file descriptor to either be inherited (C<$on> is true or missing) |
117
|
|
|
|
|
|
|
or not C<$on> is false). |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
Free portability pro-tip: it seems native win32 perls ignore $^F and set |
120
|
|
|
|
|
|
|
all file handles to be inherited by default - but this function can switch |
121
|
|
|
|
|
|
|
it off. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=back |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=head1 PORTABILITY NOTES |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
On POSIX systems, this module currently calls vfork+exec, spawn, or |
128
|
|
|
|
|
|
|
fork+exec, depending on the platform. If your platform has a good vfork or |
129
|
|
|
|
|
|
|
spawn but is misdetected and falls back to slow fork+exec, drop me a note. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
On win32, the C<_spawn> family of functions is used, and the module tries |
132
|
|
|
|
|
|
|
hard to patch the new process into perl's internal pid table, so the pid |
133
|
|
|
|
|
|
|
returned should work with other Perl functions such as waitpid. Also, |
134
|
|
|
|
|
|
|
win32 doesn't have a meaningful way to quote arguments containing |
135
|
|
|
|
|
|
|
"special" characters, so this module tries it's best to quote those |
136
|
|
|
|
|
|
|
strings itself. Other typical platform limitations (such as being able to |
137
|
|
|
|
|
|
|
only have 64 or so subprocesses) are not worked around. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 AUTHOR |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Marc Lehmann |
142
|
|
|
|
|
|
|
http://home.schmorp.de/ |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=cut |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
1 |
147
|
|
|
|
|
|
|
|