root/sapi/fpm/fpm/fpm_php_trace.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fpm_php_trace_dump
  2. fpm_php_trace

   1 
   2         /* $Id: fpm_php_trace.c,v 1.27.2.1 2008/11/15 00:57:24 anight Exp $ */
   3         /* (c) 2007,2008 Andrei Nigmatulin */
   4 
   5 #include "fpm_config.h"
   6 
   7 #if HAVE_FPM_TRACE
   8 
   9 #include "php.h"
  10 #include "php_main.h"
  11 
  12 #include <stdio.h>
  13 #include <stddef.h>
  14 #if HAVE_INTTYPES_H
  15 # include <inttypes.h>
  16 #else
  17 # include <stdint.h>
  18 #endif
  19 #include <unistd.h>
  20 #include <sys/time.h>
  21 #include <sys/types.h>
  22 #include <errno.h>
  23 
  24 #include "fpm_trace.h"
  25 #include "fpm_php_trace.h"
  26 #include "fpm_children.h"
  27 #include "fpm_worker_pool.h"
  28 #include "fpm_process_ctl.h"
  29 #include "fpm_scoreboard.h"
  30 
  31 #include "zlog.h"
  32 
  33 
  34 #define valid_ptr(p) ((p) && 0 == ((p) & (sizeof(long) - 1)))
  35 
  36 #if SIZEOF_LONG == 4
  37 #define PTR_FMT "08"
  38 #elif SIZEOF_LONG == 8
  39 #define PTR_FMT "016"
  40 #endif
  41 
  42 
  43 static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog) /* {{{ */
  44 {
  45         int callers_limit = 20;
  46         pid_t pid = child->pid;
  47         struct timeval tv;
  48         static const int buf_size = 1024;
  49         char buf[buf_size];
  50         long execute_data;
  51         long path_translated;
  52         long l;
  53 
  54         gettimeofday(&tv, 0);
  55 
  56         zlog_print_time(&tv, buf, buf_size);
  57 
  58         fprintf(slowlog, "\n%s [pool %s] pid %d\n", buf, child->wp->config->name, (int) pid);
  59 
  60         if (0 > fpm_trace_get_long((long) &SG(request_info).path_translated, &l)) {
  61                 return -1;
  62         }
  63 
  64         path_translated = l;
  65 
  66         if (0 > fpm_trace_get_strz(buf, buf_size, path_translated)) {
  67                 return -1;
  68         }
  69 
  70         fprintf(slowlog, "script_filename = %s\n", buf);
  71 
  72         if (0 > fpm_trace_get_long((long) &EG(current_execute_data), &l)) {
  73                 return -1;
  74         }
  75 
  76         execute_data = l;
  77 
  78         while (execute_data) {
  79                 long function;
  80                 long function_name;
  81                 long file_name;
  82                 long prev;
  83                 uint lineno = 0;
  84 
  85                 if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, func), &l)) {
  86                         return -1;
  87                 }
  88 
  89                 function = l;
  90 
  91                 if (valid_ptr(function)) {
  92                         if (0 > fpm_trace_get_long(function + offsetof(zend_function, common.function_name), &l)) {
  93                                 return -1;
  94                         }
  95 
  96                         function_name = l;
  97 
  98                         if (function_name == 0) {
  99                                 uint32_t *call_info = (uint32_t *)&l;
 100                                 if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, This.u1.type_info), &l)) {
 101                                         return -1;
 102                                 }
 103 
 104                                 if (ZEND_CALL_KIND_EX((*call_info) >> 24) == ZEND_CALL_TOP_CODE) {
 105                                         return 0;
 106                                 } else if (ZEND_CALL_KIND_EX(*(call_info) >> 24) == ZEND_CALL_NESTED_CODE) {
 107                                         memcpy(buf, "[INCLUDE_OR_EVAL]", sizeof("[INCLUDE_OR_EVAL]"));
 108                                 } else {
 109                                         ZEND_ASSERT(0);
 110                                 }
 111                         } else {
 112                                 if (0 > fpm_trace_get_strz(buf, buf_size, function_name + offsetof(zend_string, val))) {
 113                                         return -1;
 114                                 }
 115 
 116                         }
 117                 } else {
 118                         memcpy(buf, "???", sizeof("???"));
 119                 }
 120                 
 121                 fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
 122 
 123                 fprintf(slowlog, "%s()", buf);
 124 
 125                 *buf = '\0';
 126 
 127                 if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) {
 128                         return -1;
 129                 }
 130 
 131                 execute_data = prev = l;
 132 
 133                 while (prev) {
 134                         zend_uchar *type;
 135 
 136                         if (0 > fpm_trace_get_long(prev + offsetof(zend_execute_data, func), &l)) {
 137                                 return -1;
 138                         }
 139 
 140                         function = l;
 141 
 142                         if (!valid_ptr(function)) {
 143                                 break;
 144                         }
 145 
 146                         type = (zend_uchar *)&l;
 147                         if (0 > fpm_trace_get_long(function + offsetof(zend_function, type), &l)) { 
 148                                 return -1;
 149                         }
 150 
 151                         if (ZEND_USER_CODE(*type)) {
 152                                 if (0 > fpm_trace_get_long(function + offsetof(zend_op_array, filename), &l)) {
 153                                         return -1;
 154                                 }
 155 
 156                                 file_name = l;
 157 
 158                                 if (0 > fpm_trace_get_strz(buf, buf_size, file_name + offsetof(zend_string, val))) {
 159                                         return -1;
 160                                 }
 161 
 162                                 if (0 > fpm_trace_get_long(prev + offsetof(zend_execute_data, opline), &l)) {
 163                                         return -1;
 164                                 }
 165 
 166                                 if (valid_ptr(l)) {
 167                                         long opline = l;
 168                                         uint32_t *lu = (uint32_t *) &l;
 169 
 170                                         if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) {
 171                                                 return -1;
 172                                         }
 173 
 174                                         lineno = *lu;
 175                                 }
 176                                 break;
 177                         } 
 178 
 179                         if (0 > fpm_trace_get_long(prev + offsetof(zend_execute_data, prev_execute_data), &l)) {
 180                                 return -1;
 181                         }
 182 
 183                         prev = l;
 184                 }
 185 
 186                 fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno);
 187 
 188                 if (0 == --callers_limit) {
 189                         break;
 190                 }
 191         }
 192 
 193         return 0;
 194 }
 195 /* }}} */
 196 
 197 void fpm_php_trace(struct fpm_child_s *child) /* {{{ */
 198 {
 199         fpm_scoreboard_update(0, 0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, child->wp->scoreboard);
 200         FILE *slowlog;
 201 
 202         zlog(ZLOG_NOTICE, "about to trace %d", (int) child->pid);
 203 
 204         slowlog = fopen(child->wp->config->slowlog, "a+");
 205 
 206         if (!slowlog) {
 207                 zlog(ZLOG_SYSERROR, "unable to open slowlog (%s)", child->wp->config->slowlog);
 208                 goto done0;
 209         }
 210 
 211         if (0 > fpm_trace_ready(child->pid)) {
 212                 goto done1;
 213         }
 214 
 215         if (0 > fpm_php_trace_dump(child, slowlog)) {
 216                 fprintf(slowlog, "+++ dump failed\n");
 217         }
 218 
 219         if (0 > fpm_trace_close(child->pid)) {
 220                 goto done1;
 221         }
 222 
 223 done1:
 224         fclose(slowlog);
 225 
 226 done0:
 227         fpm_pctl_kill(child->pid, FPM_PCTL_CONT);
 228         child->tracer = 0;
 229 
 230         zlog(ZLOG_NOTICE, "finished trace of %d", (int) child->pid);
 231 }
 232 /* }}} */
 233 
 234 #endif
 235 

/* [<][>][^][v][top][bottom][index][help] */