summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTsuyoshi Sadakata <sadapon2008@gmail.com>2019-07-25 23:22:45 +0900
committerJakub Zelenka <bukka@php.net>2019-08-26 18:05:11 +0100
commitffcf57fa187f55b6e2cf3e6de43b03332cc750de (patch)
tree8d42093ddb0c061722e281c77645cdcd21d5f7ab
parent461db524001fbcbd3344a08651f3a64c775967d6 (diff)
downloadphp-git-ffcf57fa187f55b6e2cf3e6de43b03332cc750de.tar.gz
Fix bug #78334 (fpm log prefix message includes wrong stdout/stderr notation)
-rw-r--r--NEWS4
-rw-r--r--sapi/fpm/fpm/fpm_stdio.c13
-rw-r--r--sapi/fpm/fpm/fpm_stdio.h2
-rw-r--r--sapi/fpm/fpm/zlog.c20
-rw-r--r--sapi/fpm/fpm/zlog.h4
-rw-r--r--sapi/fpm/tests/log-bwd-multiple-msgs-stdout-stderr.phpt50
-rw-r--r--sapi/fpm/tests/logtool.inc7
-rw-r--r--sapi/fpm/tests/tester.inc4
8 files changed, 95 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 0e6efd76cd..515f423160 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,10 @@ PHP NEWS
. Fixed bug #77812 (Interactive mode does not support PHP 7.3-style heredoc).
(cmb, Nikita)
+- FPM:
+ . Fixed bug #78334 (fpm log prefix message includes wrong stdout/stderr
+ notation). (Tsuyoshi Sadakata)
+
- Intl:
. Ensure IDNA2003 rules are used with idn_to_ascii() and idn_to_utf8()
when requested. (Sara)
diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
index 03d15cbf0d..fde9c9144c 100644
--- a/sapi/fpm/fpm/fpm_stdio.c
+++ b/sapi/fpm/fpm/fpm_stdio.c
@@ -144,11 +144,22 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
zlog_stream_init_ex(log_stream, ZLOG_WARNING, STDERR_FILENO);
zlog_stream_set_decorating(log_stream, child->wp->config->decorate_workers_output);
zlog_stream_set_wrapping(log_stream, ZLOG_TRUE);
- zlog_stream_set_msg_prefix(log_stream, "[pool %s] child %d said into %s: ",
+ zlog_stream_set_msg_prefix(log_stream, STREAM_SET_MSG_PREFIX_FMT,
child->wp->config->name, (int) child->pid, is_stdout ? "stdout" : "stderr");
zlog_stream_set_msg_quoting(log_stream, ZLOG_TRUE);
+ zlog_stream_set_is_stdout(log_stream, is_stdout);
+ zlog_stream_set_child_pid(log_stream, (int)child->pid);
} else {
log_stream = child->log_stream;
+ // if fd type (stdout/stderr) or child's pid is changed,
+ // then the stream will be finished and msg's prefix will be reinitialized
+ if (log_stream->is_stdout != (unsigned int)is_stdout || log_stream->child_pid != (int)child->pid) {
+ zlog_stream_finish(log_stream);
+ zlog_stream_set_msg_prefix(log_stream, STREAM_SET_MSG_PREFIX_FMT,
+ child->wp->config->name, (int) child->pid, is_stdout ? "stdout" : "stderr");
+ zlog_stream_set_is_stdout(log_stream, is_stdout);
+ zlog_stream_set_child_pid(log_stream, (int)child->pid);
+ }
}
while (fifo_in || fifo_out) {
diff --git a/sapi/fpm/fpm/fpm_stdio.h b/sapi/fpm/fpm/fpm_stdio.h
index 7ebe80e66e..ef96508459 100644
--- a/sapi/fpm/fpm/fpm_stdio.h
+++ b/sapi/fpm/fpm/fpm_stdio.h
@@ -5,6 +5,8 @@
#include "fpm_worker_pool.h"
+#define STREAM_SET_MSG_PREFIX_FMT "[pool %s] child %d said into %s: "
+
int fpm_stdio_init_main();
int fpm_stdio_init_final();
int fpm_stdio_init_child(struct fpm_worker_pool_s *wp);
diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c
index 09193fd5ac..ddfed2aef9 100644
--- a/sapi/fpm/fpm/zlog.c
+++ b/sapi/fpm/fpm/zlog.c
@@ -563,6 +563,18 @@ void zlog_stream_set_wrapping(struct zlog_stream *stream, zlog_bool wrap) /* {{{
}
/* }}} */
+void zlog_stream_set_is_stdout(struct zlog_stream *stream, zlog_bool is_stdout) /* {{{ */
+{
+ stream->is_stdout = is_stdout ? 1 : 0;
+}
+/* }}} */
+
+void zlog_stream_set_child_pid(struct zlog_stream *stream, int child_pid) /* {{{ */
+{
+ stream->child_pid = child_pid;
+}
+/* }}} */
+
void zlog_stream_set_msg_quoting(struct zlog_stream *stream, zlog_bool quote) /* {{{ */
{
stream->msg_quote = quote && stream->decorate ? 1 : 0;
@@ -583,9 +595,11 @@ zlog_bool zlog_stream_set_msg_prefix(struct zlog_stream *stream, const char *fmt
len = vsnprintf(buf, MAX_WRAPPING_PREFIX_LENGTH - 1, fmt, args);
va_end(args);
- stream->msg_prefix = malloc(len + 1);
- if (stream->msg_prefix == NULL) {
- return ZLOG_FALSE;
+ if (stream->msg_prefix_len < len) {
+ stream->msg_prefix = stream->msg_prefix_len ? realloc(stream->msg_prefix, len + 1) : malloc(len + 1);
+ if (stream->msg_prefix == NULL) {
+ return ZLOG_FALSE;
+ }
}
memcpy(stream->msg_prefix, buf, len);
stream->msg_prefix[len] = 0;
diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h
index 6e96048d09..679996041b 100644
--- a/sapi/fpm/fpm/zlog.h
+++ b/sapi/fpm/fpm/zlog.h
@@ -73,8 +73,10 @@ struct zlog_stream {
unsigned int wrap:1;
unsigned int msg_quote:1;
unsigned int decorate:1;
+ unsigned int is_stdout:1;
int fd;
int line;
+ int child_pid;
const char *function;
struct zlog_stream_buffer buf;
size_t len;
@@ -92,6 +94,8 @@ void zlog_stream_init(struct zlog_stream *stream, int flags);
void zlog_stream_init_ex(struct zlog_stream *stream, int flags, int fd);
void zlog_stream_set_decorating(struct zlog_stream *stream, zlog_bool decorate);
void zlog_stream_set_wrapping(struct zlog_stream *stream, zlog_bool wrap);
+void zlog_stream_set_is_stdout(struct zlog_stream *stream, zlog_bool is_stdout);
+void zlog_stream_set_child_pid(struct zlog_stream *stream, int child_pid);
void zlog_stream_set_msg_quoting(struct zlog_stream *stream, zlog_bool quote);
zlog_bool zlog_stream_set_msg_prefix(struct zlog_stream *stream, const char *fmt, ...)
__attribute__ ((format(printf,2,3)));
diff --git a/sapi/fpm/tests/log-bwd-multiple-msgs-stdout-stderr.phpt b/sapi/fpm/tests/log-bwd-multiple-msgs-stdout-stderr.phpt
new file mode 100644
index 0000000000..376a972bac
--- /dev/null
+++ b/sapi/fpm/tests/log-bwd-multiple-msgs-stdout-stderr.phpt
@@ -0,0 +1,50 @@
+--TEST--
+FPM: Buffered worker output decorated log with multiple continuous messages (stdout/stderr mixed)
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+require_once "tester.inc";
+
+$cfg = <<<EOT
+[global]
+error_log = {{FILE:LOG}}
+[unconfined]
+listen = {{ADDR}}
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 1
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+catch_workers_output = yes
+EOT;
+
+$code = <<<EOT
+<?php
+file_put_contents('php://stdout', "msg 1 - ");
+usleep(1);
+file_put_contents('php://stderr', "msg 2 - ");
+usleep(1);
+file_put_contents('php://stderr', "msg 3");
+EOT;
+
+$tester = new FPM\Tester($cfg, $code);
+$tester->start();
+$tester->expectLogStartNotices();
+$tester->request()->expectEmptyBody();
+$tester->request()->expectEmptyBody();
+$tester->terminate();
+$tester->expectLogLine('msg 1 - ', false);
+$tester->expectLogLine('msg 2 - msg 3', true);
+$tester->close();
+
+?>
+Done
+--EXPECT--
+Done
+--CLEAN--
+<?php
+require_once "tester.inc";
+FPM\Tester::clean();
+?>
diff --git a/sapi/fpm/tests/logtool.inc b/sapi/fpm/tests/logtool.inc
index 678f11ca46..78523635d0 100644
--- a/sapi/fpm/tests/logtool.inc
+++ b/sapi/fpm/tests/logtool.inc
@@ -6,6 +6,7 @@ class LogTool
{
const P_TIME = '\[\d\d-\w\w\w-\d{4} \d\d:\d\d:\d\d\]';
const P_PREFIX = '\[pool unconfined\] child \d+ said into stderr: ';
+ const P_PREFIX_STDOUT = '\[pool unconfined\] child \d+ said into stdout: ';
const FINAL_SUFFIX = ', pipe is closed';
/**
@@ -130,7 +131,7 @@ class LogTool
* @param bool $decorated
* @return bool
*/
- public function checkWrappedMessage(array $lines, bool $terminated = true, bool $decorated = true)
+ public function checkWrappedMessage(array $lines, bool $terminated = true, bool $decorated = true, bool $is_stderr = true)
{
if ($this->message === null) {
throw new \LogicException('The message has not been set');
@@ -140,7 +141,7 @@ class LogTool
'/^(%s %s: %s)"([^"]*)"(.*)?$/',
self::P_TIME,
$this->getExpectedLevel(),
- self::P_PREFIX
+ $is_stderr ? self::P_PREFIX : self::P_PREFIX_STDOUT
);
} else {
$this->pattern = null;
@@ -157,7 +158,7 @@ class LogTool
$suffixPattern = sprintf(
'/^%s %s: %s(.*)$/',
self::P_TIME, $this->getExpectedLevel(),
- self::P_PREFIX
+ $is_stderr ? self::P_PREFIX : self::P_PREFIX_STDOUT
);
$line = $lines[++$idx];
if (preg_match($suffixPattern, $line, $matches) === 0) {
diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc
index 70c03ad70f..001b7d6a54 100644
--- a/sapi/fpm/tests/tester.inc
+++ b/sapi/fpm/tests/tester.inc
@@ -1080,7 +1080,7 @@ class Tester
* @param string $message
* @return bool
*/
- public function expectLogLine(string $message)
+ public function expectLogLine(string $message, bool $is_stderr = true)
{
$messageLen = strlen($message);
$limit = $messageLen > 1024 ? $messageLen + 16 : 1024;
@@ -1090,7 +1090,7 @@ class Tester
$this->message("LOG LINE: " . ($logLines[0] ?? ''));
}
- return $this->logTool->checkWrappedMessage($logLines, false);
+ return $this->logTool->checkWrappedMessage($logLines, false, true, $is_stderr);
}
/**