Skip to content
10 changes: 10 additions & 0 deletions sapi/fpm/fpm/fpm_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{
break;
case '1' : /* SIGUSR1 */
zlog(ZLOG_DEBUG, "received SIGUSR1");

/* fpm_stdio_init_final tied STDERR fd with error_log fd. This affects logging to the
* access.log if it was configured to write to the stderr. Check #8885. */
if (0 > fpm_stdio_restore_original_stderr()) {
zlog(ZLOG_SYSERROR, "failed to restore original STDERR descriptor, access.log records may appear in the error_log");
}

if (0 == fpm_stdio_open_error_log(1)) {
zlog(ZLOG_NOTICE, "error log file re-opened");
} else {
Expand All @@ -118,6 +125,9 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{
}
/* else no access log are set */

/* We need to tie stderr with error_log in the master process after log files reload. Check #8885. */
fpm_stdio_init_final();

break;
case '2' : /* SIGUSR2 */
zlog(ZLOG_DEBUG, "received SIGUSR2");
Expand Down
5 changes: 5 additions & 0 deletions sapi/fpm/fpm/fpm_process_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "fpm_worker_pool.h"
#include "fpm_scoreboard.h"
#include "fpm_sockets.h"
#include "fpm_stdio.h"
#include "zlog.h"


Expand Down Expand Up @@ -82,6 +83,10 @@ static void fpm_pctl_exec(void) /* {{{ */
zlog(ZLOG_WARNING, "concurrent reloads may be unstable");
}

if (0 > fpm_stdio_restore_original_stderr()) {
zlog(ZLOG_SYSERROR, "failed to restore original STDERR descriptor, access.log and slowlog records may appear in error_log");
}

zlog(ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
Expand Down
38 changes: 34 additions & 4 deletions sapi/fpm/fpm/fpm_stdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "fpm_stdio.h"
#include "zlog.h"

static int fd_stderr_original = -1;
static int fd_stdout[2];
static int fd_stderr[2];

Expand Down Expand Up @@ -67,6 +68,12 @@ int fpm_stdio_init_final() /* {{{ */
/* prevent duping if logging to syslog */
if (fpm_globals.error_log_fd > 0 && fpm_globals.error_log_fd != STDERR_FILENO) {

/* php-fpm loses STDERR fd after call of the dup2 below. Check #8555. */
if (0 > fpm_stdio_save_original_stderr()) {
zlog(ZLOG_SYSERROR, "failed to save original STDERR descriptor, access.log records may appear in error_log");
return -1;
}

/* there might be messages to stderr from other parts of the code, we need to log them all */
if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) {
zlog(ZLOG_SYSERROR, "failed to init stdio: dup2()");
Expand All @@ -85,6 +92,33 @@ int fpm_stdio_init_final() /* {{{ */
}
/* }}} */

int fpm_stdio_save_original_stderr(void) /* {{{ */
{
zlog(ZLOG_DEBUG, "saving original STDERR fd: dup()");
fd_stderr_original = dup(STDERR_FILENO);
return fd_stderr_original;
}
/* }}} */

int fpm_stdio_restore_original_stderr(void) /* {{{ */
{
zlog(ZLOG_DEBUG, "restoring original STDERR fd: dup2()");
if (-1 != fd_stderr_original) {
zlog(ZLOG_DEBUG, "restoring original STDERR fd: dup2()");
if (0 > dup2(fd_stderr_original, STDERR_FILENO)) {
return -1;
} else {
close(fd_stderr_original);
}
} else {
zlog(ZLOG_DEBUG, "original STDERR fd is not restored, maybe function is called from a child: dup2()");
return -1;
}

return 0;
}
/* }}} */

int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
{
#ifdef HAVE_SYSLOG_H
Expand Down Expand Up @@ -336,10 +370,6 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
}

if (reopen) {
if (fpm_use_error_log()) {
dup2(fd, STDERR_FILENO);
}

dup2(fd, fpm_globals.error_log_fd);
close(fd);
fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */
Expand Down
2 changes: 2 additions & 0 deletions sapi/fpm/fpm/fpm_stdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ void fpm_stdio_child_use_pipes(struct fpm_child_s *child);
int fpm_stdio_parent_use_pipes(struct fpm_child_s *child);
int fpm_stdio_discard_pipes(struct fpm_child_s *child);
int fpm_stdio_open_error_log(int reopen);
int fpm_stdio_save_original_stderr(void);
int fpm_stdio_restore_original_stderr(void);

#endif