credential-cache: close stderr in daemon process

If the stderr of "git credential-cache" is redirected to a
pipe, the reader on the other end of a pipe may be surprised
that the pipe remains open long after the process exits.
This happens because we may auto-spawn a daemon which is
long-lived, and which keeps stderr open.

We can solve this by redirecting the daemon's stderr to
/dev/null once we are ready to go into our event loop. We
would not want to do so before then, because we may want to
report errors about the setup (e.g., failure to establish
the listening socket).

This does mean that we will not report errors we encounter
for specific clients. That's acceptable, as such errors
should be rare (e.g., clients sending buggy requests).
However, we also provide an escape hatch: if you want to see
these later messages, you can provide the "--debug" option
to keep stderr open.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2014-09-14 03:35:06 -04:00 committed by Junio C Hamano
parent 96db324a73
commit f5e3c0b9d0
2 changed files with 26 additions and 5 deletions

View File

@ -8,7 +8,7 @@ git-credential-cache--daemon - Temporarily store user credentials in memory
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
git credential-cache--daemon <socket> git credential-cache--daemon [--debug] <socket>
DESCRIPTION DESCRIPTION
----------- -----------
@ -21,6 +21,10 @@ for `git-credential-cache` clients. Clients may store and retrieve
credentials. Each credential is held for a timeout specified by the credentials. Each credential is held for a timeout specified by the
client; once no credentials are held, the daemon exits. client; once no credentials are held, the daemon exits.
If the `--debug` option is specified, the daemon does not close its
stderr stream, and may output extra diagnostics to it even after it has
begun listening for clients.
GIT GIT
--- ---
Part of the linkgit:git[1] suite Part of the linkgit:git[1] suite

View File

@ -2,6 +2,7 @@
#include "credential.h" #include "credential.h"
#include "unix-socket.h" #include "unix-socket.h"
#include "sigchain.h" #include "sigchain.h"
#include "parse-options.h"
static const char *socket_path; static const char *socket_path;
@ -201,7 +202,7 @@ static int serve_cache_loop(int fd)
return 1; return 1;
} }
static void serve_cache(const char *socket_path) static void serve_cache(const char *socket_path, int debug)
{ {
int fd; int fd;
@ -211,6 +212,10 @@ static void serve_cache(const char *socket_path)
printf("ok\n"); printf("ok\n");
fclose(stdout); fclose(stdout);
if (!debug) {
if (!freopen("/dev/null", "w", stderr))
die_errno("unable to point stderr to /dev/null");
}
while (serve_cache_loop(fd)) while (serve_cache_loop(fd))
; /* nothing */ ; /* nothing */
@ -252,16 +257,28 @@ static void check_socket_directory(const char *path)
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
socket_path = argv[1]; static const char *usage[] = {
"git-credential-cache--daemon [opts] <socket_path>",
NULL
};
int debug = 0;
const struct option options[] = {
OPT_BOOL(0, "debug", &debug,
N_("print debugging messages to stderr")),
OPT_END()
};
argc = parse_options(argc, argv, NULL, options, usage, 0);
socket_path = argv[0];
if (!socket_path) if (!socket_path)
die("usage: git-credential-cache--daemon <socket_path>"); usage_with_options(usage, options);
check_socket_directory(socket_path); check_socket_directory(socket_path);
atexit(cleanup_socket); atexit(cleanup_socket);
sigchain_push_common(cleanup_socket_on_signal); sigchain_push_common(cleanup_socket_on_signal);
serve_cache(socket_path); serve_cache(socket_path, debug);
return 0; return 0;
} }