Back to index

php5  5.3.10
Classes | Functions
fpm_children.h File Reference
#include <sys/time.h>
#include <sys/types.h>
#include "fpm_worker_pool.h"
#include "fpm_events.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  fpm_child_s

Functions

int fpm_children_create_initial (struct fpm_worker_pool_s *wp)
int fpm_children_free (struct fpm_child_s *child)
void fpm_children_bury ()
int fpm_children_init_main ()
int fpm_children_make (struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug)

Function Documentation

Definition at line 177 of file fpm_children.c.

{
       int status;
       pid_t pid;
       struct fpm_child_s *child;

       while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
              char buf[128];
              int severity = ZLOG_NOTICE;
              int restart_child = 1;

              child = fpm_child_find(pid);

              if (WIFEXITED(status)) {

                     snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status));

                     /* if it's been killed because of dynamic process management
                      * don't restart it automaticaly
                      */
                     if (child && child->idle_kill) {
                            restart_child = 0;
                     }

                     if (WEXITSTATUS(status) != 0) {
                            severity = ZLOG_WARNING;
                     }

              } else if (WIFSIGNALED(status)) {
                     const char *signame = fpm_signal_names[WTERMSIG(status)];
                     const char *have_core = WCOREDUMP(status) ? " - core dumped" : "";

                     if (signame == NULL) {
                            signame = "";
                     }

                     snprintf(buf, sizeof(buf), "on signal %d (%s%s)", WTERMSIG(status), signame, have_core);

                     /* if it's been killed because of dynamic process management
                      * don't restart it automaticaly
                      */
                     if (child && child->idle_kill && WTERMSIG(status) == SIGQUIT) {
                            restart_child = 0;
                     }

                     if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */
                            severity = ZLOG_WARNING;
                     }
              } else if (WIFSTOPPED(status)) {

                     zlog(ZLOG_NOTICE, "child %d stopped for tracing", (int) pid);

                     if (child && child->tracer) {
                            child->tracer(child);
                     }

                     continue;
              }

              if (child) {
                     struct fpm_worker_pool_s *wp = child->wp;
                     struct timeval tv1, tv2;

                     fpm_child_unlink(child);

                     fpm_scoreboard_proc_free(wp->scoreboard, child->scoreboard_i);

                     fpm_clock_get(&tv1);

                     timersub(&tv1, &child->started, &tv2);

                     if (restart_child) {
                            if (!fpm_pctl_can_spawn_children()) {
                                   severity = ZLOG_DEBUG;
                            }
                            zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", child->wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
                     } else {
                            zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process managment after %ld.%06d seconds from start", child->wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
                     }

                     fpm_child_close(child, 1 /* in event_loop */);

                     fpm_pctl_child_exited();

                     if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) {
                            time_t now = tv1.tv_sec;
                            int restart_condition = 1;
                            int i;

                            last_faults[fault++] = now;

                            if (fault == fpm_global_config.emergency_restart_threshold) {
                                   fault = 0;
                            }

                            for (i = 0; i < fpm_global_config.emergency_restart_threshold; i++) {
                                   if (now - last_faults[i] > fpm_global_config.emergency_restart_interval) {
                                          restart_condition = 0;
                                          break;
                                   }
                            }

                            if (restart_condition) {

                                   zlog(ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);

                                   fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
                            }
                     }

                     if (restart_child) {
                            fpm_children_make(wp, 1 /* in event loop */, 1, 0);

                            if (fpm_globals.is_child) {
                                   break;
                            }
                     }
              } else {
                     zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s. Please open a bug report (https://bugs.php.net).", pid, buf);
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 435 of file fpm_children.c.

{
       if (wp->config->pm == PM_STYLE_ONDEMAND) {
              wp->ondemand_event = (struct fpm_event_s *)malloc(sizeof(struct fpm_event_s));

              if (!wp->ondemand_event) {
                     zlog(ZLOG_ERROR, "[pool %s] unable to malloc the ondemand socket event", wp->config->name);
                     // FIXME handle crash
                     return 1;
              }

              memset(wp->ondemand_event, 0, sizeof(struct fpm_event_s));
              fpm_event_set(wp->ondemand_event, wp->listening_socket, FPM_EV_READ | FPM_EV_EDGE, fpm_pctl_on_socket_accept, wp);
              wp->socket_event_set = 1;
              fpm_event_add(wp->ondemand_event, 0);

              return 1;
       }
       return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int fpm_children_free ( struct fpm_child_s child)

Definition at line 164 of file fpm_children.c.

{
       struct fpm_child_s *next;

       for (; child; child = next) {
              next = child->next;
              fpm_child_close(child, 0 /* in_event_loop */);
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 457 of file fpm_children.c.

{
       if (fpm_global_config.emergency_restart_threshold &&
              fpm_global_config.emergency_restart_interval) {

              last_faults = malloc(sizeof(time_t) * fpm_global_config.emergency_restart_threshold);

              if (!last_faults) {
                     return -1;
              }

              memset(last_faults, 0, sizeof(time_t) * fpm_global_config.emergency_restart_threshold);
       }

       if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_children_cleanup, 0)) {
              return -1;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int fpm_children_make ( struct fpm_worker_pool_s wp,
int  in_event_loop,
int  nb_to_spawn,
int  is_debug 
)

Definition at line 361 of file fpm_children.c.

{
       pid_t pid;
       struct fpm_child_s *child;
       int max;
       static int warned = 0;

       if (wp->config->pm == PM_STYLE_DYNAMIC) {
              if (!in_event_loop) { /* starting */
                     max = wp->config->pm_start_servers;
              } else {
                     max = wp->running_children + nb_to_spawn;
              }
       } else if (wp->config->pm == PM_STYLE_ONDEMAND) {
              if (!in_event_loop) { /* starting */
                     max = 0; /* do not create any child at startup */
              } else {
                     max = wp->running_children + nb_to_spawn;
              }
       } else { /* PM_STYLE_STATIC */
              max = wp->config->pm_max_children;
       }

       /*
        * fork children while:
        *   - fpm_pctl_can_spawn_children : FPM is running in a NORMAL state (aka not restart, stop or reload)
        *   - wp->running_children < max  : there is less than the max process for the current pool
        *   - (fpm_global_config.process_max < 1 || fpm_globals.running_children < fpm_global_config.process_max):
        *     if fpm_global_config.process_max is set, FPM has not fork this number of processes (globaly)
        */
       while (fpm_pctl_can_spawn_children() && wp->running_children < max && (fpm_global_config.process_max < 1 || fpm_globals.running_children < fpm_global_config.process_max)) {

              warned = 0;
              child = fpm_resources_prepare(wp);

              if (!child) {
                     return 2;
              }

              pid = fork();

              switch (pid) {

                     case 0 :
                            fpm_child_resources_use(child);
                            fpm_globals.is_child = 1;
                            fpm_child_init(wp);
                            return 0;

                     case -1 :
                            zlog(ZLOG_SYSERROR, "fork() failed");

                            fpm_resources_discard(child);
                            return 2;

                     default :
                            child->pid = pid;
                            fpm_clock_get(&child->started);
                            fpm_parent_resources_use(child);

                            zlog(is_debug ? ZLOG_DEBUG : ZLOG_NOTICE, "[pool %s] child %d started", wp->config->name, (int) pid);
              }

       }

       if (!warned && fpm_global_config.process_max > 0 && fpm_globals.running_children >= fpm_global_config.process_max) {
              warned = 1;
              zlog(ZLOG_WARNING, "The maximum number of processes has been reached. Please review your configuration and consider raising 'process.max'");
       }

       return 1; /* we are done */
}

Here is the call graph for this function:

Here is the caller graph for this function: