Commit 1006caf8 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Merge branch 'master' of https://github.com/thinred/nghttp2 into thinred-master

parents 780a0381 97566ce4
...@@ -564,6 +564,9 @@ void exec_binary_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) { ...@@ -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) { if (execve(argv[0], argv.get(), envp.get()) == -1) {
auto error = errno; auto error = errno;
LOG(ERROR) << "execve failed: errno=" << error; LOG(ERROR) << "execve failed: errno=" << error;
...@@ -1059,12 +1062,7 @@ void fill_default_config() { ...@@ -1059,12 +1062,7 @@ void fill_default_config() {
mod_config()->accesslog_file = nullptr; mod_config()->accesslog_file = nullptr;
mod_config()->accesslog_syslog = false; mod_config()->accesslog_syslog = false;
mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT);
#if defined(__ANDROID__) || defined(ANDROID)
// Android does not have /dev/stderr. Use /proc/self/fd/2 instead.
mod_config()->errorlog_file = strcopy("/proc/self/fd/2");
#else // !__ANDROID__ && ANDROID
mod_config()->errorlog_file = strcopy("/dev/stderr"); mod_config()->errorlog_file = strcopy("/dev/stderr");
#endif // !__ANDROID__ && ANDROID
mod_config()->errorlog_syslog = false; mod_config()->errorlog_syslog = false;
mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf"); mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf");
mod_config()->syslog_facility = LOG_DAEMON; mod_config()->syslog_facility = LOG_DAEMON;
...@@ -1768,6 +1766,9 @@ int main(int argc, char **argv) { ...@@ -1768,6 +1766,9 @@ int main(int argc, char **argv) {
create_config(); create_config();
fill_default_config(); fill_default_config();
// make copy of stderr
util::store_original_fds();
// First open log files with default configuration, so that we can // First open log files with default configuration, so that we can
// log errors/warnings while reading configuration files. // log errors/warnings while reading configuration files.
reopen_log_files(); reopen_log_files();
......
...@@ -326,31 +326,25 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv, ...@@ -326,31 +326,25 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
int reopen_log_files() { int reopen_log_files() {
int res = 0; int res = 0;
int new_accesslog_fd = -1;
int new_errorlog_fd = -1;
auto lgconf = log_config(); auto lgconf = log_config();
if (lgconf->accesslog_fd != -1) {
close(lgconf->accesslog_fd);
lgconf->accesslog_fd = -1;
}
if (!get_config()->accesslog_syslog && get_config()->accesslog_file) { if (!get_config()->accesslog_syslog && get_config()->accesslog_file) {
lgconf->accesslog_fd = new_accesslog_fd = util::open_log_file(get_config()->accesslog_file.get());
util::reopen_log_file(get_config()->accesslog_file.get());
if (lgconf->accesslog_fd == -1) { if (new_accesslog_fd == -1) {
LOG(ERROR) << "Failed to open accesslog file " LOG(ERROR) << "Failed to open accesslog file "
<< get_config()->accesslog_file.get(); << get_config()->accesslog_file.get();
res = -1; res = -1;
} }
} }
int new_errorlog_fd = -1;
if (!get_config()->errorlog_syslog && get_config()->errorlog_file) { if (!get_config()->errorlog_syslog && get_config()->errorlog_file) {
new_errorlog_fd = util::reopen_log_file(get_config()->errorlog_file.get()); new_errorlog_fd = util::open_log_file(get_config()->errorlog_file.get());
if (new_errorlog_fd == -1) { if (new_errorlog_fd == -1) {
if (lgconf->errorlog_fd != -1) { if (lgconf->errorlog_fd != -1) {
...@@ -365,16 +359,13 @@ int reopen_log_files() { ...@@ -365,16 +359,13 @@ int reopen_log_files() {
} }
} }
if (lgconf->errorlog_fd != -1) { util::close_log_file(lgconf->accesslog_fd);
close(lgconf->errorlog_fd); util::close_log_file(lgconf->errorlog_fd);
lgconf->errorlog_fd = -1;
lgconf->errorlog_tty = false;
}
if (new_errorlog_fd != -1) { lgconf->accesslog_fd = new_accesslog_fd;
lgconf->errorlog_fd = new_errorlog_fd; lgconf->errorlog_fd = new_errorlog_fd;
lgconf->errorlog_tty = isatty(lgconf->errorlog_fd); lgconf->errorlog_tty = (new_errorlog_fd == -1) ?
} false : isatty(new_errorlog_fd);
return res; return res;
} }
......
...@@ -657,22 +657,40 @@ std::string numeric_name(const struct sockaddr *sa, socklen_t salen) { ...@@ -657,22 +657,40 @@ std::string numeric_name(const struct sockaddr *sa, socklen_t salen) {
return host.data(); return host.data();
} }
int reopen_log_file(const char *path) { static int STDERR_COPY = -1;
#if defined(__ANDROID__) || defined(ANDROID) static int STDOUT_COPY = -1;
int fd;
if (strcmp("/proc/self/fd/1", path) == 0 || void store_original_fds() {
strcmp("/proc/self/fd/2", path) == 0) { // 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);
}
// We will get permission denied error when O_APPEND is used for void restore_original_fds() {
// these paths. dup2(STDERR_COPY, STDERR_FILENO);
fd = }
open(path, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP);
} else { void close_log_file(int &fd) {
fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, if (fd != STDERR_COPY && fd != STDOUT_COPY && fd != -1) {
S_IRUSR | S_IWUSR | S_IRGRP); close(fd);
}
fd = -1;
}
int open_log_file(const char *path) {
if (strcmp(path, "/dev/stdout") == 0 ||
strcmp(path, "/proc/self/fd/1") == 0) {
return STDOUT_COPY;
}
if (strcmp(path, "/dev/stderr") == 0 ||
strcmp(path, "/proc/self/fd/2") == 0) {
return STDERR_COPY;
} }
#elif defined O_CLOEXEC #if defined O_CLOEXEC
auto fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, auto fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP); S_IRUSR | S_IWUSR | S_IRGRP);
......
...@@ -516,10 +516,23 @@ bool numeric_host(const char *hostname); ...@@ -516,10 +516,23 @@ bool numeric_host(const char *hostname);
// failed, "unknown" is returned. // failed, "unknown" is returned.
std::string numeric_name(const struct sockaddr *sa, socklen_t salen); 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).
void close_log_file(int &fd);
// Opens |path| with O_APPEND enabled. If file does not exist, it is // Opens |path| with O_APPEND enabled. If file does not exist, it is
// created first. This function returns file descriptor referring the // created first. This function returns file descriptor referring the
// opened file if it succeeds, or -1. // opened file if it succeeds, or -1.
int reopen_log_file(const char *path); int open_log_file(const char *path);
// Returns ASCII dump of |data| of length |len|. Only ASCII printable // Returns ASCII dump of |data| of length |len|. Only ASCII printable
// characters are preserved. Other characters are replaced with ".". // characters are preserved. Other characters are replaced with ".".
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment