diff options
| author | Pete Wyckoff <pw@padd.com> | 2012-04-22 16:30:58 -0400 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2012-04-24 14:54:24 -0700 | 
| commit | 7fb8e163bdfdc5ffb69b98f3f05ef0dbade4e677 (patch) | |
| tree | fd59cfc42d64520337820b4485c744096db4d4fd | |
| parent | fdec2eb8ebbf995a77e2ab9971565c792b52944a (diff) | |
| download | git-7fb8e163bdfdc5ffb69b98f3f05ef0dbade4e677.tar.gz | |
git-remote-testgit: fix race when spawning fast-import
Test "pushing to local repo" in t5800-remote-helpers can hang
due to a race condition in git-remote-testgit.  Fix it by
setting stdin to unbuffered.
On the writer side, "git push" invokes push_refs_with_export(),
which sends to stdout the command "export\n" and immediately
starts up "git fast-export".  The latter writes its output stream
to the same stdout.
On the reader side, remote helper "git-remote-testgit" reads from
stdin to get its next command.  It uses getc() to read characters
from libc up until \n.  Libc has buffered a potentially much
larger chunk of stdin.  When it sees the "export\n" command, it
forks "git fast-import" to read the stream.
If fast-export finishes before git fast-import starts, the
fast-export output can end up in libc's buffer in
git-remote-testgit, rather than in git fast-import.  The latter
hangs indefinitely on a now-empty stdin.
Signed-off-by: Pete Wyckoff <pw@padd.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
| -rw-r--r-- | git-remote-testgit.py | 7 | ||||
| -rwxr-xr-x | t/t5800-remote-helpers.sh | 13 | 
2 files changed, 20 insertions, 0 deletions
| diff --git a/git-remote-testgit.py b/git-remote-testgit.py index 3dc4851cfc..5f3ebd244d 100644 --- a/git-remote-testgit.py +++ b/git-remote-testgit.py @@ -22,6 +22,7 @@ except ImportError:      _digest = sha.new  import sys  import os +import time  sys.path.insert(0, os.getenv("GITPYTHONLIB","."))  from git_remote_helpers.util import die, debug, warn @@ -204,6 +205,11 @@ def read_one_line(repo):      """Reads and processes one command.      """ +    sleepy = os.environ.get("GIT_REMOTE_TESTGIT_SLEEPY") +    if sleepy: +        debug("Sleeping %d sec before readline" % int(sleepy)) +        time.sleep(int(sleepy)) +      line = sys.stdin.readline()      cmdline = line @@ -258,6 +264,7 @@ def main(args):      more = True +    sys.stdin = os.fdopen(sys.stdin.fileno(), 'r', 0)      while (more):          more = read_one_line(repo) diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh index 1c62001fce..5702334510 100755 --- a/t/t5800-remote-helpers.sh +++ b/t/t5800-remote-helpers.sh @@ -72,6 +72,19 @@ test_expect_success 'pushing to local repo' '  	compare_refs localclone HEAD server HEAD  ' +# Generally, skip this test.  It demonstrates a now-fixed race in +# git-remote-testgit, but is too slow to leave in for general use. +: test_expect_success 'racily pushing to local repo' ' +	test_when_finished "rm -rf server2 localclone2" && +	cp -a server server2 && +	git clone "testgit::${PWD}/server2" localclone2 && +	(cd localclone2 && +	echo content >>file && +	git commit -a -m three && +	GIT_REMOTE_TESTGIT_SLEEPY=2 git push) && +	compare_refs localclone2 HEAD server2 HEAD +' +  test_expect_success 'synch with changes from localclone' '  	(cd clone &&  	 git pull) | 
