Skip to content

Commit 014b1b3

Browse files
committed
Store zlog stream in each child so it can be reused
This change results in using the same buffer for multiple stdio events which should fix inconsistencies of handling messages that are not ended with a new line and possibly very long messages that are split to multiple events.
1 parent 4d6b0b5 commit 014b1b3

File tree

8 files changed

+92
-53
lines changed

8 files changed

+92
-53
lines changed

sapi/fpm/fpm/fpm_children.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ static struct fpm_child_s *fpm_child_alloc() /* {{{ */
5757

5858
static void fpm_child_free(struct fpm_child_s *child) /* {{{ */
5959
{
60+
if (child->log_stream) {
61+
zlog_stream_close(child->log_stream);
62+
free(child->log_stream);
63+
}
6064
free(child);
6165
}
6266
/* }}} */

sapi/fpm/fpm/fpm_children.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "fpm_worker_pool.h"
1111
#include "fpm_events.h"
12+
#include "zlog.h"
1213

1314
int fpm_children_create_initial(struct fpm_worker_pool_s *wp);
1415
int fpm_children_free(struct fpm_child_s *child);
@@ -30,6 +31,7 @@ struct fpm_child_s {
3031
int idle_kill;
3132
pid_t pid;
3233
int scoreboard_i;
34+
struct zlog_stream *log_stream;
3335
};
3436

3537
#endif

sapi/fpm/fpm/fpm_request.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "fpm_children.h"
1818
#include "fpm_scoreboard.h"
1919
#include "fpm_status.h"
20+
#include "fpm_stdio.h"
2021
#include "fpm_request.h"
2122
#include "fpm_log.h"
2223

@@ -200,6 +201,7 @@ void fpm_request_end(void) /* {{{ */
200201
#endif
201202
proc->memory = memory;
202203
fpm_scoreboard_proc_release(proc);
204+
fpm_stdio_flush_child();
203205
}
204206
/* }}} */
205207

sapi/fpm/fpm/fpm_stdio.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@
2323
static int fd_stdout[2];
2424
static int fd_stderr[2];
2525

26-
static void fpm_stdio_cleanup(int which, void *arg) /* {{{ */
27-
{
28-
zlog_cleanup();
29-
}
30-
/* }}} */
31-
3226
int fpm_stdio_init_main() /* {{{ */
3327
{
3428
int fd = open("/dev/null", O_RDWR);
@@ -37,9 +31,6 @@ int fpm_stdio_init_main() /* {{{ */
3731
zlog(ZLOG_SYSERROR, "failed to init stdio: open(\"/dev/null\")");
3832
return -1;
3933
}
40-
if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_stdio_cleanup, 0)) {
41-
return -1;
42-
}
4334

4435
if (0 > dup2(fd, STDIN_FILENO) || 0 > dup2(fd, STDOUT_FILENO)) {
4536
zlog(ZLOG_SYSERROR, "failed to init stdio: dup2()");
@@ -116,6 +107,12 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
116107
}
117108
/* }}} */
118109

110+
int fpm_stdio_flush_child() /* {{{ */
111+
{
112+
return write(STDERR_FILENO, "\0", 1);
113+
}
114+
/* }}} */
115+
119116
static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
120117
{
121118
static const int max_buf_size = 1024;
@@ -126,9 +123,9 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
126123
struct fpm_event_s *event;
127124
int fifo_in = 1, fifo_out = 1;
128125
int in_buf = 0;
129-
int read_fail = 0;
126+
int read_fail = 0, finish_log_stream = 0;
130127
int res;
131-
struct zlog_stream stream;
128+
struct zlog_stream *log_stream;
132129

133130
if (!arg) {
134131
return;
@@ -142,12 +139,17 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
142139
event = &child->ev_stderr;
143140
}
144141

145-
zlog_stream_init_ex(&stream, ZLOG_WARNING, STDERR_FILENO);
146-
zlog_stream_set_decorating(&stream, child->wp->config->decorate_workers_output);
147-
zlog_stream_set_wrapping(&stream, ZLOG_TRUE);
148-
zlog_stream_set_msg_prefix(&stream, "[pool %s] child %d said into %s: ",
149-
child->wp->config->name, (int) child->pid, is_stdout ? "stdout" : "stderr");
150-
zlog_stream_set_msg_quoting(&stream, ZLOG_TRUE);
142+
if (!child->log_stream) {
143+
log_stream = child->log_stream = malloc(sizeof(struct zlog_stream));
144+
zlog_stream_init_ex(log_stream, ZLOG_WARNING, STDERR_FILENO);
145+
zlog_stream_set_decorating(log_stream, child->wp->config->decorate_workers_output);
146+
zlog_stream_set_wrapping(log_stream, ZLOG_TRUE);
147+
zlog_stream_set_msg_prefix(log_stream, "[pool %s] child %d said into %s: ",
148+
child->wp->config->name, (int) child->pid, is_stdout ? "stdout" : "stderr");
149+
zlog_stream_set_msg_quoting(log_stream, ZLOG_TRUE);
150+
} else {
151+
log_stream = child->log_stream;
152+
}
151153

152154
while (fifo_in || fifo_out) {
153155
if (fifo_in) {
@@ -160,6 +162,11 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
160162
}
161163
} else {
162164
in_buf += res;
165+
/* if buffer ends with \0, then the stream will be finished */
166+
if (!buf[in_buf - 1]) {
167+
finish_log_stream = 1;
168+
in_buf--;
169+
}
163170
}
164171
}
165172

@@ -173,25 +180,25 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
173180
if (nl) {
174181
/* we should print each new line int the new message */
175182
int out_len = nl - buf;
176-
zlog_stream_str(&stream, buf, out_len);
177-
zlog_stream_finish(&stream);
183+
zlog_stream_str(log_stream, buf, out_len);
184+
zlog_stream_finish(log_stream);
178185
/* skip new line */
179186
out_len++;
180187
/* move data in the buffer */
181188
memmove(buf, buf + out_len, in_buf - out_len);
182189
in_buf -= out_len;
183190
} else if (in_buf == max_buf_size - 1 || !fifo_in) {
184191
/* we should print if no more space in the buffer or no more data to come */
185-
zlog_stream_str(&stream, buf, in_buf);
192+
zlog_stream_str(log_stream, buf, in_buf);
186193
in_buf = 0;
187194
}
188195
}
189196
}
190197
}
191198

192199
if (read_fail) {
193-
zlog_stream_set_msg_suffix(&stream, NULL, ", pipe is closed");
194-
zlog_stream_close(&stream);
200+
zlog_stream_set_msg_suffix(log_stream, NULL, ", pipe is closed");
201+
zlog_stream_finish(log_stream);
195202
if (read_fail < 0) {
196203
zlog(ZLOG_SYSERROR, "unable to read what child say");
197204
}
@@ -205,8 +212,8 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
205212
close(child->fd_stderr);
206213
child->fd_stderr = -1;
207214
}
208-
} else {
209-
zlog_stream_close(&stream);
215+
} else if (finish_log_stream) {
216+
zlog_stream_finish(log_stream);
210217
}
211218
}
212219
/* }}} */

sapi/fpm/fpm/fpm_stdio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
int fpm_stdio_init_main();
1010
int fpm_stdio_init_final();
1111
int fpm_stdio_init_child(struct fpm_worker_pool_s *wp);
12+
int fpm_stdio_flush_child();
1213
int fpm_stdio_prepare_pipes(struct fpm_child_s *child);
1314
void fpm_stdio_child_use_pipes(struct fpm_child_s *child);
1415
int fpm_stdio_parent_use_pipes(struct fpm_child_s *child);

sapi/fpm/fpm/zlog.c

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ static int zlog_fd = -1;
2929
static int zlog_level = ZLOG_NOTICE;
3030
static int zlog_limit = ZLOG_DEFAULT_LIMIT;
3131
static zlog_bool zlog_buffering = ZLOG_DEFAULT_BUFFERING;
32-
static struct zlog_stream_buffer zlog_buffer = {NULL, 0};
3332
static int launched = 0;
3433
static void (*external_logger)(int, char *, size_t) = NULL;
3534

@@ -128,16 +127,6 @@ int zlog_set_buffering(zlog_bool buffering) /* {{{ */
128127
}
129128
/* }}} */
130129

131-
void zlog_cleanup() /* {{{ */
132-
{
133-
if (zlog_buffer.data) {
134-
free(zlog_buffer.data);
135-
zlog_buffer.data = NULL;
136-
zlog_buffer.size = 0;
137-
}
138-
}
139-
/* }}} */
140-
141130
static inline size_t zlog_truncate_buf(char *buf, size_t buf_size, size_t space_left) /* {{{ */
142131
{
143132
memcpy(buf + buf_size - sizeof("...") + 1 - space_left, "...", sizeof("...") - 1);
@@ -304,16 +293,7 @@ static zlog_bool zlog_stream_buf_alloc_ex(struct zlog_stream *stream, size_t nee
304293
buf = realloc(stream->buf.data, size);
305294
} else {
306295
size = MIN(zlog_limit, MAX(size, needed));
307-
if (stream->shared_buffer && zlog_buffer.data) {
308-
if (zlog_buffer.size < size) {
309-
buf = realloc(stream->buf.data, size);
310-
} else {
311-
buf = zlog_buffer.data;
312-
size = zlog_buffer.size;
313-
}
314-
} else {
315-
buf = malloc(size);
316-
}
296+
buf = malloc(size);
317297
}
318298

319299
if (buf == NULL) {
@@ -322,10 +302,6 @@ static zlog_bool zlog_stream_buf_alloc_ex(struct zlog_stream *stream, size_t nee
322302

323303
stream->buf.data = buf;
324304
stream->buf.size = size;
325-
if (stream->shared_buffer) {
326-
zlog_buffer.data = buf;
327-
zlog_buffer.size = size;
328-
}
329305

330306
return 1;
331307
}
@@ -554,7 +530,6 @@ static inline void zlog_stream_init_internal(
554530
stream->prefix_buffer = (flags & ZLOG_LEVEL_MASK) >= zlog_level &&
555531
(stream->use_fd || stream->use_stderr || stream->use_syslog);
556532
stream->fd = fd > -1 ? fd : STDERR_FILENO;
557-
stream->shared_buffer = external_logger == NULL;
558533
}
559534
/* }}} */
560535

@@ -858,7 +833,7 @@ zlog_bool zlog_stream_finish(struct zlog_stream *stream) /* {{{ */
858833

859834
void zlog_stream_destroy(struct zlog_stream *stream) /* {{{ */
860835
{
861-
if (!stream->shared_buffer && stream->buf.data != NULL) {
836+
if (stream->buf.data != NULL) {
862837
free(stream->buf.data);
863838
}
864839
if (stream->msg_prefix != NULL) {

sapi/fpm/fpm/zlog.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ int zlog_set_limit(int new_value);
2424
int zlog_set_buffering(zlog_bool buffering);
2525
const char *zlog_get_level_name(int log_level);
2626
void zlog_set_launched(void);
27-
void zlog_cleanup();
2827

2928
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
3029

@@ -75,7 +74,6 @@ struct zlog_stream {
7574
unsigned int wrap:1;
7675
unsigned int msg_quote:1;
7776
unsigned int decorate:1;
78-
unsigned int shared_buffer:1;
7977
int fd;
8078
int line;
8179
const char *function;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
FPM: Buffered worker output decorated log with multiple continuous messages
3+
--SKIPIF--
4+
<?php include "skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
8+
require_once "tester.inc";
9+
10+
$cfg = <<<EOT
11+
[global]
12+
error_log = {{FILE:LOG}}
13+
[unconfined]
14+
listen = {{ADDR}}
15+
pm = dynamic
16+
pm.max_children = 5
17+
pm.start_servers = 1
18+
pm.min_spare_servers = 1
19+
pm.max_spare_servers = 3
20+
catch_workers_output = yes
21+
EOT;
22+
23+
$code = <<<EOT
24+
<?php
25+
file_put_contents('php://stderr', "msg 1 - ");
26+
usleep(1);
27+
file_put_contents('php://stderr', "msg 2 - ");
28+
usleep(1);
29+
file_put_contents('php://stderr', "msg 3");
30+
EOT;
31+
32+
$tester = new FPM\Tester($cfg, $code);
33+
$tester->start();
34+
$tester->expectLogStartNotices();
35+
$tester->request()->expectEmptyBody();
36+
$tester->request()->expectEmptyBody();
37+
$tester->terminate();
38+
$tester->expectLogLine('msg 1 - msg 2 - msg 3');
39+
$tester->expectLogLine('msg 1 - msg 2 - msg 3');
40+
$tester->close();
41+
42+
?>
43+
Done
44+
--EXPECT--
45+
Done
46+
--CLEAN--
47+
<?php
48+
require_once "tester.inc";
49+
FPM\Tester::clean();
50+
?>

0 commit comments

Comments
 (0)