summaryrefslogtreecommitdiffstats
path: root/4007.patch
diff options
context:
space:
mode:
authorRemi Collet <remi@remirepo.net>2019-06-04 17:25:13 +0200
committerRemi Collet <remi@remirepo.net>2019-06-04 17:25:13 +0200
commitdf0d009fb7e277fe4fa7cc35f1b2695a2bea8df5 (patch)
treeef0eb5499c25abaabd3c6feb071859929a8ca1ea /4007.patch
parent1ae654915e9f82e616c02056c5183d51df5d1cbf (diff)
test build for https://bugs.php.net/77653
Diffstat (limited to '4007.patch')
-rw-r--r--4007.patch687
1 files changed, 687 insertions, 0 deletions
diff --git a/4007.patch b/4007.patch
new file mode 100644
index 0000000..9958737
--- /dev/null
+++ b/4007.patch
@@ -0,0 +1,687 @@
+From 730630808024373663a730be93d52c580334810d Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sun, 31 Mar 2019 16:56:17 +0100
+Subject: [PATCH 1/5] Fix logging in shutdown function
+
+---
+ sapi/fpm/fpm/fpm_stdio.c | 20 +++++++--
+ sapi/fpm/tests/log-bm-in-shutdown-fn.phpt | 49 +++++++++++++++++++++++
+ 2 files changed, 65 insertions(+), 4 deletions(-)
+ create mode 100644 sapi/fpm/tests/log-bm-in-shutdown-fn.phpt
+
+diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
+index 03d15cbf0d7c..75c4d8e9c262 100644
+--- a/sapi/fpm/fpm/fpm_stdio.c
++++ b/sapi/fpm/fpm/fpm_stdio.c
+@@ -106,9 +106,11 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
+ }
+ /* }}} */
+
++#define FPM_STDIO_CMD_FLUSH "\0fscf"
++
+ int fpm_stdio_flush_child() /* {{{ */
+ {
+- return write(STDERR_FILENO, "\0", 1);
++ return write(STDERR_FILENO, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH));
+ }
+ /* }}} */
+
+@@ -162,10 +164,20 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ }
+ } else {
+ in_buf += res;
+- /* if buffer ends with \0, then the stream will be finished */
+- if (!buf[in_buf - 1]) {
++ /* check if buffer should be flushed */
++ if (!buf[in_buf - 1] && in_buf >= sizeof(FPM_STDIO_CMD_FLUSH) &&
++ !memcmp(buf + in_buf - sizeof(FPM_STDIO_CMD_FLUSH),
++ FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
++ /* if buffer ends with flush cmd, then the stream will be finished */
++ finish_log_stream = 1;
++ in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
++ } else if (!buf[0] && in_buf > sizeof(FPM_STDIO_CMD_FLUSH) &&
++ !memcmp(buf, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
++ /* if buffer starts with flush cmd, then the stream will be finished */
+ finish_log_stream = 1;
+- in_buf--;
++ in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
++ /* move data behind the flush cmd */
++ memmove(buf, buf + sizeof(FPM_STDIO_CMD_FLUSH), in_buf);
+ }
+ }
+ }
+diff --git a/sapi/fpm/tests/log-bm-in-shutdown-fn.phpt b/sapi/fpm/tests/log-bm-in-shutdown-fn.phpt
+new file mode 100644
+index 000000000000..f968bf9f08bc
+--- /dev/null
++++ b/sapi/fpm/tests/log-bm-in-shutdown-fn.phpt
+@@ -0,0 +1,49 @@
++--TEST--
++FPM: Log message in shutdown function
++--SKIPIF--
++<?php include "skipif.inc"; ?>
++--FILE--
++<?php
++
++require_once "tester.inc";
++
++$cfg = <<<EOT
++[global]
++error_log = {{FILE:LOG}}
++log_limit = 1024
++log_buffering = yes
++[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
++register_shutdown_function(function() {
++ error_log(str_repeat('e', 80));
++});
++EOT;
++
++$tester = new FPM\Tester($cfg, $code);
++$tester->start();
++$tester->expectLogStartNotices();
++$tester->request()->expectEmptyBody();
++$tester->terminate();
++$tester->expectFastCGIErrorMessage('e', 1050, 80);
++$tester->expectLogMessage('NOTICE: PHP message: ' . str_repeat('e', 80), 1050);
++$tester->close();
++
++?>
++Done
++--EXPECT--
++Done
++--CLEAN--
++<?php
++require_once "tester.inc";
++FPM\Tester::clean();
++?>
+
+From 336ea9174b75fc33dd11a83f386df97b357b605f Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sun, 31 Mar 2019 17:55:29 +0100
+Subject: [PATCH 2/5] Move stdio flush behind request shutdown
+
+---
+ sapi/fpm/fpm/fpm_main.c | 3 +++
+ sapi/fpm/fpm/fpm_request.c | 2 --
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
+index 483fabe9d850..bfd82a1c2e11 100644
+--- a/sapi/fpm/fpm/fpm_main.c
++++ b/sapi/fpm/fpm/fpm_main.c
+@@ -90,6 +90,7 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
+ #include "fpm.h"
+ #include "fpm_request.h"
+ #include "fpm_status.h"
++#include "fpm_stdio.h"
+ #include "fpm_conf.h"
+ #include "fpm_php.h"
+ #include "fpm_log.h"
+@@ -1977,6 +1978,8 @@ consult the installation file that came with this distribution, or visit \n\
+
+ php_request_shutdown((void *) 0);
+
++ fpm_stdio_flush_child();
++
+ requests++;
+ if (UNEXPECTED(max_requests && (requests == max_requests))) {
+ fcgi_request_set_keep(request, 0);
+diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
+index 65f9c4ae441c..2aa503891ed9 100644
+--- a/sapi/fpm/fpm/fpm_request.c
++++ b/sapi/fpm/fpm/fpm_request.c
+@@ -16,7 +16,6 @@
+ #include "fpm_children.h"
+ #include "fpm_scoreboard.h"
+ #include "fpm_status.h"
+-#include "fpm_stdio.h"
+ #include "fpm_request.h"
+ #include "fpm_log.h"
+
+@@ -200,7 +199,6 @@ void fpm_request_end(void) /* {{{ */
+ #endif
+ proc->memory = memory;
+ fpm_scoreboard_proc_release(proc);
+- fpm_stdio_flush_child();
+ }
+ /* }}} */
+
+
+From a2c3ccb024b1a634e34dcff9573635e61a1fe1d7 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Sun, 21 Apr 2019 17:39:11 +0100
+Subject: [PATCH 3/5] Create a new IO ctrl pipe for flushing log stream
+
+---
+ sapi/fpm/fpm/fpm_children.h | 4 +-
+ sapi/fpm/fpm/fpm_stdio.c | 79 ++++++++++++++++++++++++++-----------
+ 2 files changed, 58 insertions(+), 25 deletions(-)
+
+diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h
+index 9d9c1fa7cb31..d755b00e243d 100644
+--- a/sapi/fpm/fpm/fpm_children.h
++++ b/sapi/fpm/fpm/fpm_children.h
+@@ -22,9 +22,9 @@ struct fpm_child_s {
+ struct fpm_child_s *prev, *next;
+ struct timeval started;
+ struct fpm_worker_pool_s *wp;
+- struct fpm_event_s ev_stdout, ev_stderr;
++ struct fpm_event_s ev_stdout, ev_stderr, ev_ioctrl;
+ int shm_slot_i;
+- int fd_stdout, fd_stderr;
++ int fd_stdout, fd_stderr, fd_ioctrl;
+ void (*tracer)(struct fpm_child_s *);
+ struct timeval slow_logged;
+ int idle_kill;
+diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
+index 75c4d8e9c262..0b41d1d8c676 100644
+--- a/sapi/fpm/fpm/fpm_stdio.c
++++ b/sapi/fpm/fpm/fpm_stdio.c
+@@ -21,6 +21,7 @@
+
+ static int fd_stdout[2];
+ static int fd_stderr[2];
++static int fd_ioctrl[2];
+
+ int fpm_stdio_init_main() /* {{{ */
+ {
+@@ -106,11 +107,36 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
+ }
+ /* }}} */
+
+-#define FPM_STDIO_CMD_FLUSH "\0fscf"
++#define FPM_STDIO_CTRL_FLUSH "f"
+
+ int fpm_stdio_flush_child() /* {{{ */
+ {
+- return write(STDERR_FILENO, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH));
++ return write(fd_ioctrl[1], FPM_STDIO_CTRL_FLUSH, sizeof(FPM_STDIO_CTRL_FLUSH));
++}
++/* }}} */
++
++static void fpm_stdio_child_ctrl(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
++{
++ static const int max_buf_size = 16;
++ int fd = ev->fd;
++ char buf[max_buf_size];
++ struct fpm_child_s *child;
++ int res;
++
++ if (!arg) {
++ return;
++ }
++ child = (struct fpm_child_s *)arg;
++
++ res = read(fd, buf, max_buf_size);
++
++ if (res <= 0) {
++ return;
++ }
++
++ if (!memcmp(buf, FPM_STDIO_CTRL_FLUSH, sizeof(FPM_STDIO_CTRL_FLUSH)) && child->log_stream) {
++ zlog_stream_finish(child->log_stream);
++ }
+ }
+ /* }}} */
+
+@@ -124,7 +150,7 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ struct fpm_event_s *event;
+ int fifo_in = 1, fifo_out = 1;
+ int in_buf = 0;
+- int read_fail = 0, finish_log_stream = 0, create_log_stream;
++ int read_fail = 0, create_log_stream;
+ int res;
+ struct zlog_stream *log_stream;
+
+@@ -164,21 +190,6 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ }
+ } else {
+ in_buf += res;
+- /* check if buffer should be flushed */
+- if (!buf[in_buf - 1] && in_buf >= sizeof(FPM_STDIO_CMD_FLUSH) &&
+- !memcmp(buf + in_buf - sizeof(FPM_STDIO_CMD_FLUSH),
+- FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
+- /* if buffer ends with flush cmd, then the stream will be finished */
+- finish_log_stream = 1;
+- in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
+- } else if (!buf[0] && in_buf > sizeof(FPM_STDIO_CMD_FLUSH) &&
+- !memcmp(buf, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
+- /* if buffer starts with flush cmd, then the stream will be finished */
+- finish_log_stream = 1;
+- in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
+- /* move data behind the flush cmd */
+- memmove(buf, buf + sizeof(FPM_STDIO_CMD_FLUSH), in_buf);
+- }
+ }
+ }
+
+@@ -226,8 +237,6 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ close(child->fd_stderr);
+ child->fd_stderr = -1;
+ }
+- } else if (finish_log_stream) {
+- zlog_stream_finish(log_stream);
+ }
+ }
+ /* }}} */
+@@ -250,12 +259,25 @@ int fpm_stdio_prepare_pipes(struct fpm_child_s *child) /* {{{ */
+ return -1;
+ }
+
+- if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) {
++ if (0 > pipe(fd_ioctrl)) {
++ zlog(ZLOG_SYSERROR, "failed to prepare the IO control pipe");
++ close(fd_stdout[0]);
++ close(fd_stdout[1]);
++ close(fd_stderr[0]);
++ close(fd_stderr[1]);
++ return -1;
++ }
++
++ if (0 > fd_set_blocked(fd_stdout[0], 0) ||
++ 0 > fd_set_blocked(fd_stderr[0], 0) ||
++ 0 > fd_set_blocked(fd_ioctrl[0], 0)) {
+ zlog(ZLOG_SYSERROR, "failed to unblock pipes");
+ close(fd_stdout[0]);
+ close(fd_stdout[1]);
+ close(fd_stderr[0]);
+ close(fd_stderr[1]);
++ close(fd_ioctrl[0]);
++ close(fd_ioctrl[1]);
+ return -1;
+ }
+ return 0;
+@@ -273,12 +295,17 @@ int fpm_stdio_parent_use_pipes(struct fpm_child_s *child) /* {{{ */
+
+ child->fd_stdout = fd_stdout[0];
+ child->fd_stderr = fd_stderr[0];
++ child->fd_ioctrl = fd_ioctrl[0];
+
+ fpm_event_set(&child->ev_stdout, child->fd_stdout, FPM_EV_READ, fpm_stdio_child_said, child);
+ fpm_event_add(&child->ev_stdout, 0);
+
+ fpm_event_set(&child->ev_stderr, child->fd_stderr, FPM_EV_READ, fpm_stdio_child_said, child);
+ fpm_event_add(&child->ev_stderr, 0);
++
++ fpm_event_set(&child->ev_ioctrl, child->fd_ioctrl, FPM_EV_READ, fpm_stdio_child_ctrl, child);
++ fpm_event_add(&child->ev_ioctrl, 0);
++
+ return 0;
+ }
+ /* }}} */
+@@ -291,9 +318,12 @@ int fpm_stdio_discard_pipes(struct fpm_child_s *child) /* {{{ */
+
+ close(fd_stdout[1]);
+ close(fd_stderr[1]);
++ close(fd_ioctrl[1]);
+
+ close(fd_stdout[0]);
+ close(fd_stderr[0]);
++ close(fd_ioctrl[0]);
++
+ return 0;
+ }
+ /* }}} */
+@@ -303,8 +333,11 @@ void fpm_stdio_child_use_pipes(struct fpm_child_s *child) /* {{{ */
+ if (child->wp->config->catch_workers_output) {
+ dup2(fd_stdout[1], STDOUT_FILENO);
+ dup2(fd_stderr[1], STDERR_FILENO);
+- close(fd_stdout[0]); close(fd_stdout[1]);
+- close(fd_stderr[0]); close(fd_stderr[1]);
++ close(fd_stdout[0]);
++ close(fd_stdout[1]);
++ close(fd_stderr[0]);
++ close(fd_stderr[1]);
++ close(fd_ioctrl[0]);
+ } else {
+ /* stdout of parent is always /dev/null */
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+
+From b6ad8cdf993f0f076dd05e8543b02f3bbf215a7b Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Mon, 27 May 2019 16:24:28 +0100
+Subject: [PATCH 4/5] Revert "Create a new IO ctrl pipe for flushing log
+ stream"
+
+This reverts commit f6f37a799ebf0c0dc5dcace0dab527a1ff567b77.
+---
+ sapi/fpm/fpm/fpm_children.h | 4 +-
+ sapi/fpm/fpm/fpm_stdio.c | 79 +++++++++++--------------------------
+ 2 files changed, 25 insertions(+), 58 deletions(-)
+
+diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h
+index d755b00e243d..9d9c1fa7cb31 100644
+--- a/sapi/fpm/fpm/fpm_children.h
++++ b/sapi/fpm/fpm/fpm_children.h
+@@ -22,9 +22,9 @@ struct fpm_child_s {
+ struct fpm_child_s *prev, *next;
+ struct timeval started;
+ struct fpm_worker_pool_s *wp;
+- struct fpm_event_s ev_stdout, ev_stderr, ev_ioctrl;
++ struct fpm_event_s ev_stdout, ev_stderr;
+ int shm_slot_i;
+- int fd_stdout, fd_stderr, fd_ioctrl;
++ int fd_stdout, fd_stderr;
+ void (*tracer)(struct fpm_child_s *);
+ struct timeval slow_logged;
+ int idle_kill;
+diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
+index 0b41d1d8c676..75c4d8e9c262 100644
+--- a/sapi/fpm/fpm/fpm_stdio.c
++++ b/sapi/fpm/fpm/fpm_stdio.c
+@@ -21,7 +21,6 @@
+
+ static int fd_stdout[2];
+ static int fd_stderr[2];
+-static int fd_ioctrl[2];
+
+ int fpm_stdio_init_main() /* {{{ */
+ {
+@@ -107,36 +106,11 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
+ }
+ /* }}} */
+
+-#define FPM_STDIO_CTRL_FLUSH "f"
++#define FPM_STDIO_CMD_FLUSH "\0fscf"
+
+ int fpm_stdio_flush_child() /* {{{ */
+ {
+- return write(fd_ioctrl[1], FPM_STDIO_CTRL_FLUSH, sizeof(FPM_STDIO_CTRL_FLUSH));
+-}
+-/* }}} */
+-
+-static void fpm_stdio_child_ctrl(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
+-{
+- static const int max_buf_size = 16;
+- int fd = ev->fd;
+- char buf[max_buf_size];
+- struct fpm_child_s *child;
+- int res;
+-
+- if (!arg) {
+- return;
+- }
+- child = (struct fpm_child_s *)arg;
+-
+- res = read(fd, buf, max_buf_size);
+-
+- if (res <= 0) {
+- return;
+- }
+-
+- if (!memcmp(buf, FPM_STDIO_CTRL_FLUSH, sizeof(FPM_STDIO_CTRL_FLUSH)) && child->log_stream) {
+- zlog_stream_finish(child->log_stream);
+- }
++ return write(STDERR_FILENO, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH));
+ }
+ /* }}} */
+
+@@ -150,7 +124,7 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ struct fpm_event_s *event;
+ int fifo_in = 1, fifo_out = 1;
+ int in_buf = 0;
+- int read_fail = 0, create_log_stream;
++ int read_fail = 0, finish_log_stream = 0, create_log_stream;
+ int res;
+ struct zlog_stream *log_stream;
+
+@@ -190,6 +164,21 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ }
+ } else {
+ in_buf += res;
++ /* check if buffer should be flushed */
++ if (!buf[in_buf - 1] && in_buf >= sizeof(FPM_STDIO_CMD_FLUSH) &&
++ !memcmp(buf + in_buf - sizeof(FPM_STDIO_CMD_FLUSH),
++ FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
++ /* if buffer ends with flush cmd, then the stream will be finished */
++ finish_log_stream = 1;
++ in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
++ } else if (!buf[0] && in_buf > sizeof(FPM_STDIO_CMD_FLUSH) &&
++ !memcmp(buf, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
++ /* if buffer starts with flush cmd, then the stream will be finished */
++ finish_log_stream = 1;
++ in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
++ /* move data behind the flush cmd */
++ memmove(buf, buf + sizeof(FPM_STDIO_CMD_FLUSH), in_buf);
++ }
+ }
+ }
+
+@@ -237,6 +226,8 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ close(child->fd_stderr);
+ child->fd_stderr = -1;
+ }
++ } else if (finish_log_stream) {
++ zlog_stream_finish(log_stream);
+ }
+ }
+ /* }}} */
+@@ -259,25 +250,12 @@ int fpm_stdio_prepare_pipes(struct fpm_child_s *child) /* {{{ */
+ return -1;
+ }
+
+- if (0 > pipe(fd_ioctrl)) {
+- zlog(ZLOG_SYSERROR, "failed to prepare the IO control pipe");
+- close(fd_stdout[0]);
+- close(fd_stdout[1]);
+- close(fd_stderr[0]);
+- close(fd_stderr[1]);
+- return -1;
+- }
+-
+- if (0 > fd_set_blocked(fd_stdout[0], 0) ||
+- 0 > fd_set_blocked(fd_stderr[0], 0) ||
+- 0 > fd_set_blocked(fd_ioctrl[0], 0)) {
++ if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) {
+ zlog(ZLOG_SYSERROR, "failed to unblock pipes");
+ close(fd_stdout[0]);
+ close(fd_stdout[1]);
+ close(fd_stderr[0]);
+ close(fd_stderr[1]);
+- close(fd_ioctrl[0]);
+- close(fd_ioctrl[1]);
+ return -1;
+ }
+ return 0;
+@@ -295,17 +273,12 @@ int fpm_stdio_parent_use_pipes(struct fpm_child_s *child) /* {{{ */
+
+ child->fd_stdout = fd_stdout[0];
+ child->fd_stderr = fd_stderr[0];
+- child->fd_ioctrl = fd_ioctrl[0];
+
+ fpm_event_set(&child->ev_stdout, child->fd_stdout, FPM_EV_READ, fpm_stdio_child_said, child);
+ fpm_event_add(&child->ev_stdout, 0);
+
+ fpm_event_set(&child->ev_stderr, child->fd_stderr, FPM_EV_READ, fpm_stdio_child_said, child);
+ fpm_event_add(&child->ev_stderr, 0);
+-
+- fpm_event_set(&child->ev_ioctrl, child->fd_ioctrl, FPM_EV_READ, fpm_stdio_child_ctrl, child);
+- fpm_event_add(&child->ev_ioctrl, 0);
+-
+ return 0;
+ }
+ /* }}} */
+@@ -318,12 +291,9 @@ int fpm_stdio_discard_pipes(struct fpm_child_s *child) /* {{{ */
+
+ close(fd_stdout[1]);
+ close(fd_stderr[1]);
+- close(fd_ioctrl[1]);
+
+ close(fd_stdout[0]);
+ close(fd_stderr[0]);
+- close(fd_ioctrl[0]);
+-
+ return 0;
+ }
+ /* }}} */
+@@ -333,11 +303,8 @@ void fpm_stdio_child_use_pipes(struct fpm_child_s *child) /* {{{ */
+ if (child->wp->config->catch_workers_output) {
+ dup2(fd_stdout[1], STDOUT_FILENO);
+ dup2(fd_stderr[1], STDERR_FILENO);
+- close(fd_stdout[0]);
+- close(fd_stdout[1]);
+- close(fd_stderr[0]);
+- close(fd_stderr[1]);
+- close(fd_ioctrl[0]);
++ close(fd_stdout[0]); close(fd_stdout[1]);
++ close(fd_stderr[0]); close(fd_stderr[1]);
+ } else {
+ /* stdout of parent is always /dev/null */
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+
+From ffad6a9ff551fce04fc0b8dd905cf5db2aac7813 Mon Sep 17 00:00:00 2001
+From: Jakub Zelenka <bukka@php.net>
+Date: Mon, 27 May 2019 16:29:09 +0100
+Subject: [PATCH 5/5] Refactor fpm_stdio_child_said
+
+---
+ sapi/fpm/fpm/fpm_stdio.c | 80 ++++++++++++++--------------------------
+ sapi/fpm/fpm/zlog.c | 8 ++--
+ 2 files changed, 32 insertions(+), 56 deletions(-)
+
+diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
+index 75c4d8e9c262..d7d2c4b0b229 100644
+--- a/sapi/fpm/fpm/fpm_stdio.c
++++ b/sapi/fpm/fpm/fpm_stdio.c
+@@ -122,10 +122,8 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ struct fpm_child_s *child;
+ int is_stdout;
+ struct fpm_event_s *event;
+- int fifo_in = 1, fifo_out = 1;
+- int in_buf = 0;
+- int read_fail = 0, finish_log_stream = 0, create_log_stream;
+- int res;
++ int in_buf = 0, pos, start;
++ int read_fail = 0, create_log_stream;
+ struct zlog_stream *log_stream;
+
+ if (!arg) {
+@@ -153,59 +151,37 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ log_stream = child->log_stream;
+ }
+
+- while (fifo_in || fifo_out) {
+- if (fifo_in) {
+- res = read(fd, buf + in_buf, max_buf_size - 1 - in_buf);
+- if (res <= 0) { /* no data */
+- fifo_in = 0;
+- if (res == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
+- /* pipe is closed or error */
+- read_fail = (res < 0) ? res : 1;
+- }
+- } else {
+- in_buf += res;
+- /* check if buffer should be flushed */
+- if (!buf[in_buf - 1] && in_buf >= sizeof(FPM_STDIO_CMD_FLUSH) &&
+- !memcmp(buf + in_buf - sizeof(FPM_STDIO_CMD_FLUSH),
+- FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
+- /* if buffer ends with flush cmd, then the stream will be finished */
+- finish_log_stream = 1;
+- in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
+- } else if (!buf[0] && in_buf > sizeof(FPM_STDIO_CMD_FLUSH) &&
+- !memcmp(buf, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
+- /* if buffer starts with flush cmd, then the stream will be finished */
+- finish_log_stream = 1;
+- in_buf -= sizeof(FPM_STDIO_CMD_FLUSH);
+- /* move data behind the flush cmd */
+- memmove(buf, buf + sizeof(FPM_STDIO_CMD_FLUSH), in_buf);
+- }
++ while (1) {
++ in_buf = read(fd, buf, max_buf_size - 1);
++ if (in_buf <= 0) { /* no data */
++ if (in_buf == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
++ /* pipe is closed or error */
++ read_fail = (in_buf < 0) ? in_buf : 1;
+ }
++ break;
+ }
+
+- if (fifo_out) {
+- if (in_buf == 0) {
+- fifo_out = 0;
+- } else {
+- char *nl;
+-
+- nl = memchr(buf, '\n', in_buf);
+- if (nl) {
+- /* we should print each new line int the new message */
+- int out_len = nl - buf;
+- zlog_stream_str(log_stream, buf, out_len);
++ for (start = 0, pos = 0; pos < in_buf; pos++) {
++ switch (buf[pos]) {
++ case '\n':
++ zlog_stream_str(log_stream, buf + start, pos - start);
+ zlog_stream_finish(log_stream);
+- /* skip new line */
+- out_len++;
+- /* move data in the buffer */
+- memmove(buf, buf + out_len, in_buf - out_len);
+- in_buf -= out_len;
+- } else if (in_buf == max_buf_size - 1 || !fifo_in) {
+- /* we should print if no more space in the buffer or no more data to come */
+- zlog_stream_str(log_stream, buf, in_buf);
+- in_buf = 0;
+- }
++ start = pos + 1;
++ break;
++ case '\0':
++ if (pos + sizeof(FPM_STDIO_CMD_FLUSH) <= in_buf &&
++ !memcmp(buf + pos, FPM_STDIO_CMD_FLUSH, sizeof(FPM_STDIO_CMD_FLUSH))) {
++ zlog_stream_str(log_stream, buf + start, pos - start);
++ zlog_stream_finish(log_stream);
++ start = pos + sizeof(FPM_STDIO_CMD_FLUSH);
++ pos = start - 1;
++ }
++ break;
+ }
+ }
++ if (start < pos) {
++ zlog_stream_str(log_stream, buf + start, pos - start);
++ }
+ }
+
+ if (read_fail) {
+@@ -226,8 +202,6 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
+ close(child->fd_stderr);
+ child->fd_stderr = -1;
+ }
+- } else if (finish_log_stream) {
+- zlog_stream_finish(log_stream);
+ }
+ }
+ /* }}} */
+diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c
+index 09193fd5ac85..21bd614a9784 100644
+--- a/sapi/fpm/fpm/zlog.c
++++ b/sapi/fpm/fpm/zlog.c
+@@ -720,14 +720,16 @@ ssize_t zlog_stream_format(struct zlog_stream *stream, const char *fmt, ...) /*
+
+ ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */
+ {
++ /* do not write anything if the stream is full or str is empty */
++ if (str_len == 0 || stream->full) {
++ return 0;
++ }
++
+ /* reset stream if it is finished */
+ if (stream->finished) {
+ stream->finished = 0;
+ stream->len = 0;
+ stream->full = 0;
+- } else if (stream->full) {
+- /* do not write anything if the stream is full */
+- return 0;
+ }
+
+ if (stream->use_buffer) {