#
#
# patch "lib/perl/Common.pm"
# from [ece342e6cdb7e8f24e9cd5f0517ad1642fd8ded5]
# to [1792ecc74728f8d91f6c5e22fccf58fee301d8d3]
#
# patch "mtn-browse"
# from [567234f0497878b4898b61d6ba4885fcb42d04fa]
# to [8d3222fb76959b757890b771b73c1db6ab922714]
#
============================================================
--- lib/perl/Common.pm ece342e6cdb7e8f24e9cd5f0517ad1642fd8ded5
+++ lib/perl/Common.pm 1792ecc74728f8d91f6c5e22fccf58fee301d8d3
@@ -53,6 +53,10 @@ use constant THRESHOLD => 20;
use constant CHUNK_SIZE => 10240;
use constant THRESHOLD => 20;
+# Constant used to represent the exception thrown when interrupting waitpid().
+
+use constant WAITPID_INTERRUPT => "waitpid-interrupt";
+
# The saved directory locations where assorted Gtk2::FileChooserDialog dialog
# windows were last used.
@@ -167,9 +171,8 @@ sub run_command($@)
$fd_err,
$fd_in,
$fd_out,
+ $my_pid,
$pid,
- $ret_val,
- $status,
$stop,
$total_bytes,
$watcher);
@@ -177,28 +180,49 @@ sub run_command($@)
# Run the command.
$fd_err = gensym();
+ $my_pid = $$;
eval
{
$pid = open3($fd_in, $fd_out, $fd_err, @args);
};
- if ($@ ne "")
+
+ # Check for errors (remember that open3() errors can happen in both the
+ # parent and child processes).
+
+ if ($@)
{
- my $dialog = Gtk2::MessageDialog->new
- (undef,
- ["modal"],
- "warning",
- "close",
- __x("The {name} subprocess could not start,\n"
- . "the system gave:\n{error_message}",
- name => Glib::Markup::escape_text($args[0]),
- error_message => Glib::Markup::escape_text($@)));
- WindowManager->instance()->allow_input(sub { $dialog->run(); });
- $dialog->destroy();
- return;
+ if ($$ != $my_pid)
+ {
+
+ # In the child process so all we can do is complain and exit.
+
+ warn(__x("open3 failed: {error_message}", error_message => $@));
+ exit(1);
+
+ }
+ else
+ {
+
+ # In the parent process so deal with the error in the usual way.
+
+ my $dialog = Gtk2::MessageDialog->new
+ (undef,
+ ["modal"],
+ "warning",
+ "close",
+ __x("The {name} subprocess could not start,\n"
+ . "the system gave:\n{error_message}",
+ name => Glib::Markup::escape_text($args[0]),
+ error_message => Glib::Markup::escape_text($@)));
+ WindowManager->instance()->allow_input(sub { $dialog->run(); });
+ $dialog->destroy();
+ return;
+
+ }
}
- # Setup a watch handler to get read our data and handle GTK2 events whilst
- # the command is running.
+ # Setup a watch handler to read our data and handle GTK2 events whilst the
+ # command is running.
$stop = $total_bytes = 0;
$$buffer = "";
@@ -236,10 +260,107 @@ sub run_command($@)
# Reap the process and deal with any errors.
- if (($ret_val = waitpid($pid, 0)) == -1)
+ for (my $i = 0; $i < 4; ++ $i)
{
- if ($! != ECHILD)
+
+ my $wait_status = 0;
+
+ # Wait for the subprocess to exit (preserving the current state of $@
+ # so that any exception that has already occurred is not lost, also
+ # ignore any errors resulting from waitpid() interruption).
+
{
+ local $@;
+ eval
+ {
+ local $SIG{ALRM} = sub { die(WAITPID_INTERRUPT); };
+ alarm(5);
+ $wait_status = waitpid($pid, 0);
+ alarm(0);
+ };
+ $wait_status = 0
+ if ($@ eq WAITPID_INTERRUPT && $wait_status < 0
+ && $! == EINTR);
+ }
+
+ # The subprocess has terminated.
+
+ if ($wait_status == $pid)
+ {
+ my $exit_status = $?;
+ if (WIFEXITED($exit_status) && WEXITSTATUS($exit_status) != 0)
+ {
+ my $dialog = Gtk2::MessageDialog->new_with_markup
+ (undef,
+ ["modal"],
+ "warning",
+ "close",
+ __x("The {name} subprocess failed with an exit status\n"
+ . "of {exit_code} and printed the following on "
+ . "stderr:\n"
+ . "{error_message}",
+ name => Glib::Markup::escape_text($args[0]),
+ exit_code => WEXITSTATUS($exit_status),
+ error_message => Glib::Markup::escape_text
+ (join("", @err))));
+ WindowManager->instance()->allow_input
+ (sub { $dialog->run(); });
+ $dialog->destroy();
+ return;
+ }
+ elsif (WIFSIGNALED($exit_status))
+ {
+ my $dialog = Gtk2::MessageDialog->new
+ (undef,
+ ["modal"],
+ "warning",
+ "close",
+ __x("The {name} subprocess was terminated by signal "
+ . "{number}.",
+ name => Glib::Markup::escape_text($args[0]),
+ number => WTERMSIG($exit_status)));
+ WindowManager->instance()->allow_input
+ (sub { $dialog->run(); });
+ $dialog->destroy();
+ return;
+ }
+ last;
+ }
+
+ # The subprocess is still there so try and kill it unless it's time to
+ # just give up.
+
+ elsif ($i < 3 && $wait_status == 0)
+ {
+ if ($i == 0)
+ {
+ kill("INT", $pid);
+ }
+ elsif ($i == 1)
+ {
+ kill("TERM", $pid);
+ }
+ else
+ {
+ kill("KILL", $pid);
+ }
+ }
+
+ # Stop if we don't have any relevant children to wait for anymore.
+
+ elsif ($wait_status < 0 && $! == ECHILD)
+ {
+ last;
+ }
+
+ # Either there is some other error with waitpid() or a child process
+ # has been reaped that we aren't interested in (in which case just
+ # ignore it).
+
+ elsif ($wait_status < 0)
+ {
+ my $err_msg = $!;
+ kill("KILL", $pid);
my $dialog = Gtk2::MessageDialog->new_with_markup
(undef,
["modal"],
@@ -251,39 +372,8 @@ sub run_command($@)
$dialog->destroy();
return;
}
+
}
- $status = $?;
- if (WIFEXITED($status) && WEXITSTATUS($status) != 0)
- {
- my $dialog = Gtk2::MessageDialog->new_with_markup
- (undef,
- ["modal"],
- "warning",
- "close",
- __x("The {name} subprocess failed with an exit status\n"
- . "of {exit_code} and printed the following on stderr:\n"
- . "{error_message}",
- name => Glib::Markup::escape_text($args[0]),
- exit_code => WEXITSTATUS($status),
- error_message => Glib::Markup::escape_text(join("", @err))));
- WindowManager->instance()->allow_input(sub { $dialog->run(); });
- $dialog->destroy();
- return;
- }
- elsif (WIFSIGNALED($status))
- {
- my $dialog = Gtk2::MessageDialog->new
- (undef,
- ["modal"],
- "warning",
- "close",
- __x("The {name} subprocess was terminated by signal {number}.",
- name => Glib::Markup::escape_text($args[0]),
- number => WTERMSIG($status)));
- WindowManager->instance()->allow_input(sub { $dialog->run(); });
- $dialog->destroy();
- return;
- }
return 1;
============================================================
--- mtn-browse 567234f0497878b4898b61d6ba4885fcb42d04fa
+++ mtn-browse 8d3222fb76959b757890b771b73c1db6ab922714
@@ -3037,15 +3037,14 @@ sub sigchld_handler()
sub sigchld_handler()
{
- my($pid,
- $status);
+ my $pid;
my $wm = WindowManager->instance();
while (($pid = waitpid(-1, WNOHANG)) > 0)
{
- $status = $?;
- if (WIFEXITED($status) || WIFSIGNALED($status))
+ my $exit_status = $?;
+ if (WIFEXITED($exit_status) || WIFSIGNALED($exit_status))
{
# If it is an mtn process then close down the relevant object so
@@ -3060,15 +3059,16 @@ sub sigchld_handler()
{
my $message;
$instance->{mtn}->closedown();
- if (WIFSIGNALED($status))
+ if (WIFSIGNALED($exit_status))
{
$message = __x("terminated by signal {number}",
- number => WTERMSIG($status));
+ number => WTERMSIG($exit_status));
}
else
{
- $message = __x("exited with status {number}",
- number => WEXITSTATUS($status));
+ $message =
+ __x("exited with status {number}",
+ number => WEXITSTATUS($exit_status));
}
my $dialog = Gtk2::MessageDialog->new
(undef,