Back to index

php5  5.3.10
Functions | Variables
fpm_stdio.c File Reference
#include "fpm_config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "php_syslog.h"
#include "fpm.h"
#include "fpm_children.h"
#include "fpm_events.h"
#include "fpm_sockets.h"
#include "fpm_stdio.h"
#include "zlog.h"

Go to the source code of this file.

Functions

int fpm_stdio_init_main ()
int fpm_stdio_init_final ()
int fpm_stdio_init_child (struct fpm_worker_pool_s *wp)
static void fpm_stdio_child_said (struct fpm_event_s *ev, short which, void *arg)
int fpm_stdio_prepare_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)
void fpm_stdio_child_use_pipes (struct fpm_child_s *child)
int fpm_stdio_open_error_log (int reopen)

Variables

static int fd_stdout [2]
static int fd_stderr [2]

Function Documentation

static void fpm_stdio_child_said ( struct fpm_event_s ev,
short  which,
void *  arg 
) [static]

Definition at line 85 of file fpm_stdio.c.

{
       static const int max_buf_size = 1024;
       int fd = ev->fd;
       char buf[max_buf_size];
       struct fpm_child_s *child;
       int is_stdout;
       struct fpm_event_s *event;
       int fifo_in = 1, fifo_out = 1;
       int is_last_message = 0;
       int in_buf = 0;
       int res;

       if (!arg) {
              return;
       }
       child = (struct fpm_child_s *)arg;
       is_stdout = (fd == child->fd_stdout);
       if (is_stdout) {
              event = &child->ev_stdout;
       } else {
              event = &child->ev_stderr;
       }

       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)) {
                                   /* just no more data ready */
                            } else { /* error or pipe is closed */

                                   if (res < 0) { /* error */
                                          zlog(ZLOG_SYSERROR, "unable to read what child say");
                                   }

                                   fpm_event_del(event);
                                   is_last_message = 1;

                                   if (is_stdout) {
                                          close(child->fd_stdout);
                                          child->fd_stdout = -1;
                                   } else {
                                          close(child->fd_stderr);
                                          child->fd_stderr = -1;
                                   }
                            }
                     } else {
                            in_buf += res;
                     }
              }

              if (fifo_out) {
                     if (in_buf == 0) {
                            fifo_out = 0;
                     } else {
                            char *nl;
                            int should_print = 0;
                            buf[in_buf] = '\0';

                            /* FIXME: there might be binary data */

                            /* we should print if no more space in the buffer */
                            if (in_buf == max_buf_size - 1) {
                                   should_print = 1;
                            }

                            /* we should print if no more data to come */
                            if (!fifo_in) {
                                   should_print = 1;
                            }

                            nl = strchr(buf, '\n');
                            if (nl || should_print) {

                                   if (nl) {
                                          *nl = '\0';
                                   }

                                   zlog(ZLOG_WARNING, "[pool %s] child %d said into %s: \"%s\"%s", child->wp->config->name,
                                     (int) child->pid, is_stdout ? "stdout" : "stderr", buf, is_last_message ? ", pipe is closed" : "");

                                   if (nl) {
                                          int out_buf = 1 + nl - buf;
                                          memmove(buf, buf + out_buf, in_buf - out_buf);
                                          in_buf -= out_buf;
                                   } else {
                                          in_buf = 0;
                                   }
                            }
                     }
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void fpm_stdio_child_use_pipes ( struct fpm_child_s child)

Definition at line 248 of file fpm_stdio.c.

{
       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]);
       } else {
              /* stdout of parent is always /dev/null */
              dup2(STDOUT_FILENO, STDERR_FILENO);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 233 of file fpm_stdio.c.

{
       if (0 == child->wp->config->catch_workers_output) { /* not required */
              return 0;
       }

       close(fd_stdout[1]);
       close(fd_stderr[1]);

       close(fd_stdout[0]);
       close(fd_stderr[0]);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 62 of file fpm_stdio.c.

{
#ifdef HAVE_SYSLOG_H
       if (fpm_globals.error_log_fd == ZLOG_SYSLOG) {
              closelog(); /* ensure to close syslog not to interrupt with PHP syslog code */
       } else
#endif
       if (fpm_globals.error_log_fd > 0) {
              close(fpm_globals.error_log_fd);
       }
       fpm_globals.error_log_fd = -1;
       zlog_set_fd(-1);

       if (wp->listening_socket != STDIN_FILENO) {
              if (0 > dup2(wp->listening_socket, STDIN_FILENO)) {
                     zlog(ZLOG_SYSERROR, "failed to init child stdio: dup2()");
                     return -1;
              }
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 44 of file fpm_stdio.c.

{
       if (fpm_global_config.daemonize) {
              /* prevent duping if logging to syslog */
              if (fpm_globals.error_log_fd > 0 && fpm_globals.error_log_fd != STDERR_FILENO) {

                     /* 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()");
                            return -1;
                     }
              }
       }
       zlog_set_launched();
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 26 of file fpm_stdio.c.

{
       int fd = open("/dev/null", O_RDWR);

       if (0 > fd) {
              zlog(ZLOG_SYSERROR, "failed to init stdio: open(\"/dev/null\")");
              return -1;
       }

       if (0 > dup2(fd, STDIN_FILENO) || 0 > dup2(fd, STDOUT_FILENO)) {
              zlog(ZLOG_SYSERROR, "failed to init stdio: dup2()");
              return -1;
       }
       close(fd);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 262 of file fpm_stdio.c.

{
       int fd;

#ifdef HAVE_SYSLOG_H
       if (!strcasecmp(fpm_global_config.error_log, "syslog")) {
              openlog(fpm_global_config.syslog_ident, LOG_PID | LOG_CONS, fpm_global_config.syslog_facility);
              fpm_globals.error_log_fd = ZLOG_SYSLOG;
              if (fpm_global_config.daemonize) {
                     zlog_set_fd(fpm_globals.error_log_fd);
              }
              return 0;
       }
#endif

       fd = open(fpm_global_config.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
       if (0 > fd) {
              zlog(ZLOG_SYSERROR, "failed to open error_log (%s)", fpm_global_config.error_log);
              return -1;
       }

       if (reopen) {
              if (fpm_global_config.daemonize) {
                     dup2(fd, STDERR_FILENO);
              }

              dup2(fd, fpm_globals.error_log_fd);
              close(fd);
              fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */
       } else {
              fpm_globals.error_log_fd = fd;
              if (fpm_global_config.daemonize) {
                     zlog_set_fd(fpm_globals.error_log_fd);
              }
       }
       fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 212 of file fpm_stdio.c.

{
       if (0 == child->wp->config->catch_workers_output) { /* not required */
              return 0;
       }

       close(fd_stdout[1]);
       close(fd_stderr[1]);

       child->fd_stdout = fd_stdout[0];
       child->fd_stderr = fd_stderr[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);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 182 of file fpm_stdio.c.

{
       if (0 == child->wp->config->catch_workers_output) { /* not required */
              return 0;
       }

       if (0 > pipe(fd_stdout)) {
              zlog(ZLOG_SYSERROR, "failed to prepare the stdout pipe");
              return -1;
       }

       if (0 > pipe(fd_stderr)) {
              zlog(ZLOG_SYSERROR, "failed to prepare the stderr pipe");
              close(fd_stdout[0]);
              close(fd_stdout[1]);
              return -1;
       }

       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]);
              return -1;
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int fd_stderr[2] [static]

Definition at line 24 of file fpm_stdio.c.

int fd_stdout[2] [static]

Definition at line 23 of file fpm_stdio.c.