mirror of
https://github.com/git/git.git
synced 2024-11-24 10:26:17 +08:00
Merge branch 'jk/git-connection-deadlock-fix'
* jk/git-connection-deadlock-fix: test core.gitproxy configuration send-pack: avoid deadlock on git:// push with failed pack-objects connect: let callers know if connection is a socket connect: treat generic proxy processes like ssh processes Conflicts: connect.c
This commit is contained in:
commit
a66fae3827
@ -344,6 +344,8 @@ int send_pack(struct send_pack_args *args,
|
|||||||
ref->status = REF_STATUS_NONE;
|
ref->status = REF_STATUS_NONE;
|
||||||
if (args->stateless_rpc)
|
if (args->stateless_rpc)
|
||||||
close(out);
|
close(out);
|
||||||
|
if (git_connection_is_socket(conn))
|
||||||
|
shutdown(fd[0], SHUT_WR);
|
||||||
if (use_sideband)
|
if (use_sideband)
|
||||||
finish_async(&demux);
|
finish_async(&demux);
|
||||||
return -1;
|
return -1;
|
||||||
|
1
cache.h
1
cache.h
@ -975,6 +975,7 @@ extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
|
|||||||
extern char *git_getpass(const char *prompt);
|
extern char *git_getpass(const char *prompt);
|
||||||
extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
|
extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
|
||||||
extern int finish_connect(struct child_process *conn);
|
extern int finish_connect(struct child_process *conn);
|
||||||
|
extern int git_connection_is_socket(struct child_process *conn);
|
||||||
extern int path_match(const char *path, int nr, char **match);
|
extern int path_match(const char *path, int nr, char **match);
|
||||||
struct extra_have_objects {
|
struct extra_have_objects {
|
||||||
int nr, alloc;
|
int nr, alloc;
|
||||||
|
35
connect.c
35
connect.c
@ -395,26 +395,28 @@ static int git_use_proxy(const char *host)
|
|||||||
return (git_proxy_command && *git_proxy_command);
|
return (git_proxy_command && *git_proxy_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void git_proxy_connect(int fd[2], char *host)
|
static struct child_process *git_proxy_connect(int fd[2], char *host)
|
||||||
{
|
{
|
||||||
const char *port = STR(DEFAULT_GIT_PORT);
|
const char *port = STR(DEFAULT_GIT_PORT);
|
||||||
const char *argv[4];
|
const char **argv;
|
||||||
struct child_process proxy;
|
struct child_process *proxy;
|
||||||
|
|
||||||
get_host_and_port(&host, &port);
|
get_host_and_port(&host, &port);
|
||||||
|
|
||||||
|
argv = xmalloc(sizeof(*argv) * 4);
|
||||||
argv[0] = git_proxy_command;
|
argv[0] = git_proxy_command;
|
||||||
argv[1] = host;
|
argv[1] = host;
|
||||||
argv[2] = port;
|
argv[2] = port;
|
||||||
argv[3] = NULL;
|
argv[3] = NULL;
|
||||||
memset(&proxy, 0, sizeof(proxy));
|
proxy = xcalloc(1, sizeof(*proxy));
|
||||||
proxy.argv = argv;
|
proxy->argv = argv;
|
||||||
proxy.in = -1;
|
proxy->in = -1;
|
||||||
proxy.out = -1;
|
proxy->out = -1;
|
||||||
if (start_command(&proxy))
|
if (start_command(proxy))
|
||||||
die("cannot start proxy %s", argv[0]);
|
die("cannot start proxy %s", argv[0]);
|
||||||
fd[0] = proxy.out; /* read from proxy stdout */
|
fd[0] = proxy->out; /* read from proxy stdout */
|
||||||
fd[1] = proxy.in; /* write to proxy stdin */
|
fd[1] = proxy->in; /* write to proxy stdin */
|
||||||
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_CMD_LEN 1024
|
#define MAX_CMD_LEN 1024
|
||||||
@ -455,7 +457,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|||||||
char *host, *path;
|
char *host, *path;
|
||||||
char *end;
|
char *end;
|
||||||
int c;
|
int c;
|
||||||
struct child_process *conn;
|
struct child_process *conn = &no_fork;
|
||||||
enum protocol protocol = PROTO_LOCAL;
|
enum protocol protocol = PROTO_LOCAL;
|
||||||
int free_path = 0;
|
int free_path = 0;
|
||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
@ -540,7 +542,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|||||||
*/
|
*/
|
||||||
char *target_host = xstrdup(host);
|
char *target_host = xstrdup(host);
|
||||||
if (git_use_proxy(host))
|
if (git_use_proxy(host))
|
||||||
git_proxy_connect(fd, host);
|
conn = git_proxy_connect(fd, host);
|
||||||
else
|
else
|
||||||
git_tcp_connect(fd, host, flags);
|
git_tcp_connect(fd, host, flags);
|
||||||
/*
|
/*
|
||||||
@ -558,7 +560,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|||||||
free(url);
|
free(url);
|
||||||
if (free_path)
|
if (free_path)
|
||||||
free(path);
|
free(path);
|
||||||
return &no_fork;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = xcalloc(1, sizeof(*conn));
|
conn = xcalloc(1, sizeof(*conn));
|
||||||
@ -607,10 +609,15 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_connection_is_socket(struct child_process *conn)
|
||||||
|
{
|
||||||
|
return conn == &no_fork;
|
||||||
|
}
|
||||||
|
|
||||||
int finish_connect(struct child_process *conn)
|
int finish_connect(struct child_process *conn)
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
if (!conn || conn == &no_fork)
|
if (!conn || git_connection_is_socket(conn))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
code = finish_command(conn);
|
code = finish_command(conn);
|
||||||
|
43
t/t5532-fetch-proxy.sh
Executable file
43
t/t5532-fetch-proxy.sh
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='fetching via git:// using core.gitproxy'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_expect_success 'setup remote repo' '
|
||||||
|
git init remote &&
|
||||||
|
(cd remote &&
|
||||||
|
echo content >file &&
|
||||||
|
git add file &&
|
||||||
|
git commit -m one
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >proxy <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
echo >&2 "proxying for $*"
|
||||||
|
cmd=`perl -e '
|
||||||
|
read(STDIN, $buf, 4);
|
||||||
|
my $n = hex($buf) - 4;
|
||||||
|
read(STDIN, $buf, $n);
|
||||||
|
my ($cmd, $other) = split /\0/, $buf;
|
||||||
|
# drop absolute-path on repo name
|
||||||
|
$cmd =~ s{ /}{ };
|
||||||
|
print $cmd;
|
||||||
|
'`
|
||||||
|
echo >&2 "Running '$cmd'"
|
||||||
|
exec $cmd
|
||||||
|
EOF
|
||||||
|
chmod +x proxy
|
||||||
|
test_expect_success 'setup local repo' '
|
||||||
|
git remote add fake git://example.com/remote &&
|
||||||
|
git config core.gitproxy ./proxy
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch through proxy works' '
|
||||||
|
git fetch fake &&
|
||||||
|
echo one >expect &&
|
||||||
|
git log -1 --format=%s FETCH_HEAD >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user