Back to index

php5  5.3.10
fpm_php_trace.c
Go to the documentation of this file.
00001 
00002        /* $Id: fpm_php_trace.c,v 1.27.2.1 2008/11/15 00:57:24 anight Exp $ */
00003        /* (c) 2007,2008 Andrei Nigmatulin */
00004 
00005 #include "fpm_config.h"
00006 
00007 #if HAVE_FPM_TRACE
00008 
00009 #include "php.h"
00010 #include "php_main.h"
00011 
00012 #include <stdio.h>
00013 #include <stddef.h>
00014 #if HAVE_INTTYPES_H
00015 # include <inttypes.h>
00016 #else
00017 # include <stdint.h>
00018 #endif
00019 #include <unistd.h>
00020 #include <sys/time.h>
00021 #include <sys/types.h>
00022 #include <errno.h>
00023 
00024 #include "fpm_trace.h"
00025 #include "fpm_php_trace.h"
00026 #include "fpm_children.h"
00027 #include "fpm_worker_pool.h"
00028 #include "fpm_process_ctl.h"
00029 
00030 #include "zlog.h"
00031 
00032 
00033 #define valid_ptr(p) ((p) && 0 == ((p) & (sizeof(long) - 1)))
00034 
00035 #if SIZEOF_LONG == 4
00036 #define PTR_FMT "08"
00037 #elif SIZEOF_LONG == 8
00038 #define PTR_FMT "016"
00039 #endif
00040 
00041 
00042 static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) /* {{{ */
00043 {
00044        int callers_limit = 20;
00045        pid_t pid = child->pid;
00046        struct timeval tv;
00047        static const int buf_size = 1024;
00048        char buf[buf_size];
00049        long execute_data;
00050        long l;
00051 
00052        gettimeofday(&tv, 0);
00053 
00054        zlog_print_time(&tv, buf, buf_size);
00055 
00056        fprintf(slowlog, "\n%s [pool %s] pid %d\n", buf, child->wp->config->name, (int) pid);
00057 
00058        if (0 > fpm_trace_get_strz(buf, buf_size, (long) &SG(request_info).path_translated)) {
00059               return -1;
00060        }
00061 
00062        fprintf(slowlog, "script_filename = %s\n", buf);
00063 
00064        if (0 > fpm_trace_get_long((long) &EG(current_execute_data), &l)) {
00065               return -1;
00066        }
00067 
00068        execute_data = l;
00069 
00070        while (execute_data) {
00071               long function;
00072               uint lineno = 0;
00073 
00074               fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
00075 
00076               if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
00077                      return -1;
00078               }
00079 
00080               function = l;
00081 
00082               if (valid_ptr(function)) {
00083                      if (0 > fpm_trace_get_strz(buf, buf_size, function + offsetof(zend_function, common.function_name))) {
00084                             return -1;
00085                      }
00086 
00087                      fprintf(slowlog, "%s()", buf);
00088               } else {
00089                      fprintf(slowlog, "???");
00090               }
00091 
00092               if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, op_array), &l)) {
00093                      return -1;
00094               }
00095 
00096               *buf = '\0';
00097 
00098               if (valid_ptr(l)) {
00099                      long op_array = l;
00100 
00101                      if (0 > fpm_trace_get_strz(buf, buf_size, op_array + offsetof(zend_op_array, filename))) {
00102                             return -1;
00103                      }
00104               }
00105 
00106               if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, opline), &l)) {
00107                      return -1;
00108               }
00109 
00110               if (valid_ptr(l)) {
00111                      long opline = l;
00112                      uint *lu = (uint *) &l;
00113 
00114                      if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) {
00115                             return -1;
00116                      }
00117 
00118                      lineno = *lu;
00119               }
00120 
00121               fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno);
00122 
00123               if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) {
00124                      return -1;
00125               }
00126 
00127               execute_data = l;
00128 
00129               if (0 == --callers_limit) {
00130                      break;
00131               }
00132        }
00133        return 0;
00134 }
00135 /* }}} */
00136 
00137 void fpm_php_trace(struct fpm_child_s *child) /* {{{ */
00138 {
00139        TSRMLS_FETCH();
00140        FILE *slowlog;
00141 
00142        zlog(ZLOG_NOTICE, "about to trace %d", (int) child->pid);
00143 
00144        slowlog = fopen(child->wp->config->slowlog, "a+");
00145 
00146        if (!slowlog) {
00147               zlog(ZLOG_SYSERROR, "unable to open slowlog (%s)", child->wp->config->slowlog);
00148               goto done0;
00149        }
00150 
00151        if (0 > fpm_trace_ready(child->pid)) {
00152               goto done1;
00153        }
00154 
00155        if (0 > fpm_php_trace_dump(child, slowlog TSRMLS_CC)) {
00156               fprintf(slowlog, "+++ dump failed\n");
00157        }
00158 
00159        if (0 > fpm_trace_close(child->pid)) {
00160               goto done1;
00161        }
00162 
00163 done1:
00164        fclose(slowlog);
00165 
00166 done0:
00167        fpm_pctl_kill(child->pid, FPM_PCTL_CONT);
00168        child->tracer = 0;
00169 
00170        zlog(ZLOG_NOTICE, "finished trace of %d", (int) child->pid);
00171 }
00172 /* }}} */
00173 
00174 #endif
00175