2
# Copyright (C) 2004-2006 MySQL AB
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; version 2 of the License.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
# This is a library file used by the Perl version of mysql-test-run,
18
# and is part of the translation of the Bourne shell script with the
23
package My::SafeProcess::Base;
26
# Utility functions for Process management
32
use base qw(Exporter);
33
our @EXPORT= qw(create_process);
39
# Retry a couple of times if fork returns EAGAIN
48
if ( not defined($pid)) {
50
croak("fork failed after: $!") if (!$retries--);
52
warn("fork failed sleep 1 second and redo: $!");
67
my $raw= $self->{EXIT_STATUS};
69
croak("Can't call exit_status before process has died")
75
my $signal_num= $raw & 127;
76
my $dumped_core= $raw & 128;
77
return 1; # Return error code
88
# Create a new process
89
# Return pid of the new process
97
my $path = delete($opts{'path'}) or die "path required";
98
my $args = delete($opts{'args'}) or die "args required";
99
my $input = delete($opts{'input'});
100
my $output = delete($opts{'output'});
101
my $error = delete($opts{'error'});
103
my $open_mode= $opts{append} ? ">>" : ">";
105
if ($^O eq "MSWin32"){
107
#printf STDERR "stdin %d, stdout %d, stderr %d\n",
108
# fileno STDIN, fileno STDOUT, fileno STDERR;
110
# input output redirect
111
my ($oldin, $oldout, $olderr);
112
open $oldin, '<&', \*STDIN or die "Failed to save old stdin: $!";
113
open $oldout, '>&', \*STDOUT or die "Failed to save old stdout: $!";
114
open $olderr, '>&', \*STDERR or die "Failed to save old stderr: $!";
117
if ( ! open(STDIN, "<", $input) ) {
118
croak("can't redirect STDIN to '$input': $!");
123
if ( ! open(STDOUT, $open_mode, $output) ) {
124
croak("can't redirect STDOUT to '$output': $!");
129
if ( $output eq $error ) {
130
if ( ! open(STDERR, ">&STDOUT") ) {
131
croak("can't dup STDOUT: $!");
134
elsif ( ! open(STDERR, $open_mode, $error) ) {
135
croak("can't redirect STDERR to '$error': $!");
140
# Magic use of 'system(1, @args)' to spawn a process
141
# and get a proper Win32 pid
142
unshift (@$args, $path);
143
my $pid= system(1, @$args);
145
print $olderr "create_process failed: $^E\n";
146
die "create_process failed: $^E";
149
# Retore IO redirects
150
open STDERR, '>&', $olderr
151
or croak("unable to reestablish STDERR");
152
open STDOUT, '>&', $oldout
153
or croak("unable to reestablish STDOUT");
154
open STDIN, '<&', $oldin
155
or croak("unable to reestablish STDIN");
156
#printf STDERR "stdin %d, stdout %d, stderr %d\n",
157
# fileno STDIN, fileno STDOUT, fileno STDERR;
162
local $SIG{PIPE}= sub { print STDERR "Got signal $@\n"; };
163
my $pipe= IO::Pipe->new();
164
my $pid= _safe_fork();
168
my $line= <$pipe>; # Wait for child to say it's ready
172
$SIG{INT}= 'DEFAULT';
174
# Make this process it's own process group to be able to kill
175
# it and any childs(that hasn't changed group themself)
176
setpgrp(0,0) if $opts{setpgrp};
178
if ( $output and !open(STDOUT, $open_mode, $output) ) {
179
croak("can't redirect STDOUT to '$output': $!");
183
if ( defined $output and $output eq $error ) {
184
if ( ! open(STDERR, ">&STDOUT") ) {
185
croak("can't dup STDOUT: $!");
188
elsif ( ! open(STDERR, $open_mode, $error) ) {
189
croak("can't redirect STDERR to '$error': $!");
194
if ( ! open(STDIN, "<", $input) ) {
195
croak("can't redirect STDIN to '$input': $!");
199
# Tell parent to continue
201
print $pipe "ready\n";
203
if ( !exec($path, @$args) ){
204
croak("Failed to exec '$path': $!");
207
croak("Should never come here");