From: Jonathan Nieder Date: Sat, 9 Jun 2012 19:14:07 -0500 Subject: debian/diff: fix intermittent SIGPIPE in large git-svn HTTP fetches This is needed for the initial "git svn clone" to finish in many repositories. It's an old bug. Thanks to Roman Kagan for figuring out the cause at last. Signed-off-by: Jonathan Nieder --- debian/changelog | 10 +++ ...svn-use-POSIX-sigprocmask-to-block-signals.diff | 79 ++++++++++++++++++++ debian/diff/0045-git-svn-ignore-SIGPIPE.diff | 51 +++++++++++++ 3 files changed, 140 insertions(+), 0 deletions(-) create mode 100644 debian/diff/0044-git-svn-use-POSIX-sigprocmask-to-block-signals.diff create mode 100644 debian/diff/0045-git-svn-ignore-SIGPIPE.diff diff --git a/debian/changelog b/debian/changelog index 9d886ab..af995ee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +git (1:1.7.2.5-3.1) stable; urgency=low + + * debian/diff/0044-git-svn-use-POSIX-sigprocmask-to-block-....diff, + debian/diff/0045-git-svn-ignore-SIGPIPE.diff: new from upstream; + git-svn: ignore SIGPIPE so serf can recover from HTTP timeouts + during a large fetch instead of dying of signal 13 (closes: + #540150). + + -- Jonathan Nieder Sat, 09 Jun 2012 19:12:17 -0500 + git (1:1.7.2.5-3) stable; urgency=low * debian/diff/0034..0042: new from the upstream maint-1.7.2 branch: diff --git a/debian/diff/0044-git-svn-use-POSIX-sigprocmask-to-block-signals.diff b/debian/diff/0044-git-svn-use-POSIX-sigprocmask-to-block-signals.diff new file mode 100644 index 0000000..44fffb8 --- /dev/null +++ b/debian/diff/0044-git-svn-use-POSIX-sigprocmask-to-block-signals.diff @@ -0,0 +1,79 @@ +From e17cb85adec53d7c476666bc1eb894b24194b356 Mon Sep 17 00:00:00 2001 +From: Roman Kagan +Date: Mon, 2 Apr 2012 17:29:32 +0400 +Subject: git-svn: use POSIX::sigprocmask to block signals + +In order to maintain consistency of the database mapping svn revision +numbers to git commit ids, rev_map_set() defers signal processing until +it's finished with an append transaction.[*] + +The conventional way to achieve this is through sigprocmask(), which is +available in perl in the standard POSIX module. + +This is implemented by this patch. One important consequence of it is +that the signal handlers won't be unconditionally set to SIG_DFL anymore +upon the first invocation of rev_map_set() as they used to. As a +result, the signals ignored by git-svn parent will remain ignored; +otherwise the behavior remains the same. + +This patch paves the way to ignoring SIGPIPE throughout git-svn which +will be done in the followup patch. + +[*] Deferring signals is not enough to ensure the database consistency: +the program may die on SIGKILL or power loss, run out of disk space, +etc. However that's a separate issue that this patch doesn't address. + +Signed-off-by: Roman Kagan +Acked-by: Eric Wong +(cherry picked from commit 037a98cd3f3efe85c6f56c4338002e4b2c7afa09) + +Signed-off-by: Jonathan Nieder +--- + git-svn.perl | 15 +++++++++------ + 1 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/git-svn.perl b/git-svn.perl +index c416358..1906f89 100755 +--- a/git-svn.perl ++++ b/git-svn.perl +@@ -1664,6 +1664,7 @@ use File::Copy qw/copy/; + use IPC::Open3; + use Memoize; # core since 5.8.0, Jul 2002 + use Memoize::Storable; ++use POSIX qw(:signal_h); + + my ($_gc_nr, $_gc_period); + +@@ -3639,11 +3640,14 @@ sub rev_map_set { + length $commit == 40 or die "arg3 must be a full SHA1 hexsum\n"; + my $db = $self->map_path($uuid); + my $db_lock = "$db.lock"; +- my $sig; ++ my $sigmask; + $update_ref ||= 0; + if ($update_ref) { +- $SIG{INT} = $SIG{HUP} = $SIG{TERM} = $SIG{ALRM} = $SIG{PIPE} = +- $SIG{USR1} = $SIG{USR2} = sub { $sig = $_[0] }; ++ $sigmask = POSIX::SigSet->new(); ++ my $signew = POSIX::SigSet->new(SIGINT, SIGHUP, SIGTERM, ++ SIGALRM, SIGPIPE, SIGUSR1, SIGUSR2); ++ sigprocmask(SIG_BLOCK, $signew, $sigmask) or ++ croak "Can't block signals: $!"; + } + mkfile($db); + +@@ -3682,9 +3686,8 @@ sub rev_map_set { + "$db_lock => $db ($!)\n"; + delete $LOCKFILES{$db_lock}; + if ($update_ref) { +- $SIG{INT} = $SIG{HUP} = $SIG{TERM} = $SIG{ALRM} = $SIG{PIPE} = +- $SIG{USR1} = $SIG{USR2} = 'DEFAULT'; +- kill $sig, $$ if defined $sig; ++ sigprocmask(SIG_SETMASK, $sigmask) or ++ croak "Can't restore signal mask: $!"; + } + } + +-- +1.7.2.5 + diff --git a/debian/diff/0045-git-svn-ignore-SIGPIPE.diff b/debian/diff/0045-git-svn-ignore-SIGPIPE.diff new file mode 100644 index 0000000..48c26f3 --- /dev/null +++ b/debian/diff/0045-git-svn-ignore-SIGPIPE.diff @@ -0,0 +1,51 @@ +From 001f278c4df87c004fa5fb0058a95b9ef62899e6 Mon Sep 17 00:00:00 2001 +From: Roman Kagan +Date: Mon, 2 Apr 2012 17:52:34 +0400 +Subject: git-svn: ignore SIGPIPE + +In HTTP with keep-alive it's not uncommon for the client to notice that +the server decided to stop maintaining the current connection only when +sending a new request. This naturally results in -EPIPE and possibly +SIGPIPE. + +The subversion library itself makes no provision for SIGPIPE. Some +combinations of the underlying libraries do (typically SIG_IGN-ing it), +some don't. + +Presumably for that reason all subversion commands set SIGPIPE to +SIG_IGN early in their main()-s. + +So should we. + +This, together with the previous patch, fixes the notorious "git-svn +died of signal 13" problem (see e.g. +http://thread.gmane.org/gmane.comp.version-control.git/134936). + +Signed-off-by: Roman Kagan +Acked-by: Eric Wong +(cherry picked from commit 6ade9bdadaf61565ee4e2ab47f66baaf41a20ecf) + +Signed-off-by: Jonathan Nieder +--- + git-svn.perl | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/git-svn.perl b/git-svn.perl +index 1906f89..66c7b44 100755 +--- a/git-svn.perl ++++ b/git-svn.perl +@@ -36,6 +36,11 @@ $ENV{TZ} = 'UTC'; + $| = 1; # unbuffer STDOUT + + sub fatal (@) { print STDERR "@_\n"; exit 1 } ++ ++# All SVN commands do it. Otherwise we may die on SIGPIPE when the remote ++# repository decides to close the connection which we expect to be kept alive. ++$SIG{PIPE} = 'IGNORE'; ++ + sub _req_svn { + require SVN::Core; # use()-ing this causes segfaults for me... *shrug* + require SVN::Ra; +-- +1.7.2.5 + -- 1.7.2.5