From 97566ce4e3b3584e4a4d67f17b467f00ea9b339b Mon Sep 17 00:00:00 2001 From: Tomasz Buchert Date: Thu, 13 Aug 2015 11:01:37 +0200 Subject: [PATCH] nghttpx: make early copy of stderr --- src/shrpx.cc | 6 ++++++ src/util.cc | 20 +++++++++++++++++--- src/util.h | 8 ++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/shrpx.cc b/src/shrpx.cc index 1efb0eea..666c882a 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -564,6 +564,9 @@ void exec_binary_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) { } } + // restores original stderr + util::restore_original_fds(); + if (execve(argv[0], argv.get(), envp.get()) == -1) { auto error = errno; LOG(ERROR) << "execve failed: errno=" << error; @@ -1763,6 +1766,9 @@ int main(int argc, char **argv) { create_config(); fill_default_config(); + // make copy of stderr + util::store_original_fds(); + // First open log files with default configuration, so that we can // log errors/warnings while reading configuration files. reopen_log_files(); diff --git a/src/util.cc b/src/util.cc index fc92039c..bfa292a8 100644 --- a/src/util.cc +++ b/src/util.cc @@ -657,9 +657,23 @@ std::string numeric_name(const struct sockaddr *sa, socklen_t salen) { return host.data(); } +static int STDERR_COPY = -1; +static int STDOUT_COPY = -1; + +void store_original_fds() { + // consider dup'ing stdout too + STDERR_COPY = dup(STDERR_FILENO); + STDOUT_COPY = STDOUT_FILENO; + // no race here, since it is called early + make_socket_closeonexec(STDERR_COPY); +} + +void restore_original_fds() { + dup2(STDERR_COPY, STDERR_FILENO); +} void close_log_file(int &fd) { - if (fd != STDERR_FILENO && fd != STDOUT_FILENO && fd != -1) { + if (fd != STDERR_COPY && fd != STDOUT_COPY && fd != -1) { close(fd); } fd = -1; @@ -669,12 +683,12 @@ int open_log_file(const char *path) { if (strcmp(path, "/dev/stdout") == 0 || strcmp(path, "/proc/self/fd/1") == 0) { - return STDOUT_FILENO; + return STDOUT_COPY; } if (strcmp(path, "/dev/stderr") == 0 || strcmp(path, "/proc/self/fd/2") == 0) { - return STDERR_FILENO; + return STDERR_COPY; } #if defined O_CLOEXEC diff --git a/src/util.h b/src/util.h index b6860a07..6463d19a 100644 --- a/src/util.h +++ b/src/util.h @@ -516,6 +516,14 @@ bool numeric_host(const char *hostname); // failed, "unknown" is returned. std::string numeric_name(const struct sockaddr *sa, socklen_t salen); +// Makes internal copy of stderr (and possibly stdout in the future), +// which is then used as pointer to /dev/stderr or /proc/self/fd/2 +void store_original_fds(); + +// Restores the original stderr that was stored with copy_original_fds +// Used just before execv +void restore_original_fds(); + // Closes |fd| which was returned by open_log_file (see below) // and sets it to -1. In the case that |fd| points to stdout or // stderr, or is -1, the descriptor is not closed (but still set to -1).