00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 #include "libts.h"
00030 #include "signals.h"
00031 #include "ProxyConfig.h"
00032 #include "P_EventSystem.h"
00033 #include "StatSystem.h"
00034 #include "proxy/Main.h"
00035 
00036 
00037 #include "ink_stack_trace.h"
00038 
00039 #if TS_HAS_PROFILER
00040 #include <google/profiler.h>
00041 #endif
00042 
00043 #if !defined(linux) && !defined(freebsd)
00044 typedef void (*SigActionFunc_t) (int sig, siginfo_t * t, void *f);
00045 #else
00046 typedef void (*SigActionFunc_t) (int sig);
00047 #endif
00048 
00049 int exited_children = 0;
00050 
00051 static volatile int sigusr1_received = 0;
00052 extern int fastmemtotal;
00053 
00054 class SignalContinuation:public Continuation
00055 {
00056 public:
00057   char *end;
00058   char *snap;
00059   int fastmemsnap;
00060     SignalContinuation()
00061   : Continuation(new_ProxyMutex())
00062   {
00063     end = snap = 0;
00064     fastmemsnap = 0;
00065     SET_HANDLER(&SignalContinuation::periodic);
00066   }
00067 
00068   int periodic(int , Event * )
00069   {
00070     if (sigusr1_received) {
00071       sigusr1_received = 0;
00072       
00073       ink_freelists_dump(stderr);
00074       if (!end)
00075         end = (char *) sbrk(0);
00076       if (!snap)
00077         snap = (char *) sbrk(0);
00078       char *now = (char *) sbrk(0);
00079       
00080       
00081       
00082       
00083       fprintf(stderr, "sbrk 0x%" PRIu64 "x from first %" PRIu64 " from last %" PRIu64 "\n",
00084               (uint64_t) ((ptrdiff_t) now), (uint64_t) ((ptrdiff_t) (now - end)),
00085               (uint64_t) ((ptrdiff_t) (now - snap)));
00086 #ifdef DEBUG
00087       int fmdelta = fastmemtotal - fastmemsnap;
00088       fprintf(stderr, "fastmem %" PRId64 " from last %" PRId64 "\n", (int64_t) fastmemtotal, (int64_t) fmdelta);
00089       fastmemsnap += fmdelta;
00090 #endif
00091       snap = now;
00092     }
00093 
00094     return EVENT_CONT;
00095   }
00096 };
00097 
00098 class TrackerContinuation:public Continuation
00099 {
00100 public:
00101   int baseline_taken;
00102   int use_baseline;
00103   TrackerContinuation()
00104     : Continuation(new_ProxyMutex())
00105   {
00106     SET_HANDLER(&TrackerContinuation::periodic);
00107     use_baseline = 0;
00108     
00109     
00110     
00111     
00112     if (getenv("MEMTRACK_BASELINE"))
00113     {
00114       use_baseline = 1;
00115     }
00116     baseline_taken = 0;
00117   }
00118 
00119   int periodic(int , Event * )
00120   {
00121     if (use_baseline) {
00122       
00123       ink_freelists_dump_baselinerel(stderr);
00124     } else {
00125       
00126       ink_freelists_dump(stderr);
00127     }
00128     if (!baseline_taken && use_baseline) {
00129       ink_freelists_snap_baseline();
00130       
00131       baseline_taken = 1;
00132     }
00133     return EVENT_CONT;
00134   }
00135 };
00136 
00137 
00138 static void
00139 interrupt_handler(int sig)
00140 {
00141   (void) sig;
00142   fprintf(stderr, "interrupt caught...exit\n");
00143   shutdown_system();
00144   _exit(1);
00145 }
00146 
00147 #if defined(linux)
00148 static void
00149 signal_handler(int sig)
00150 #else
00151 static void
00152 signal_handler(int sig, siginfo_t * t, void *c)
00153 #endif
00154 {
00155   if (sig == SIGUSR1) {
00156     sigusr1_received = 1;
00157     return;
00158   }
00159 
00160   char sig_msg[2048];
00161 #if !defined(linux) && !defined(freebsd)
00162   
00163   
00164   
00165   
00166   
00167   
00168   
00169   
00170   
00171   
00172   
00173   
00174   if (t) {
00175     if (t->si_code <= 0) {
00176       
00177 #if defined(solaris)
00178       snprintf(sig_msg, sizeof(sig_msg), "NOTE: Traffic Server received User Sig %d from pid: %d uid: %d\n",
00179                sig, (int)t->si_pid, (int)t->si_uid);
00180 #else
00181       snprintf(sig_msg, sizeof(sig_msg), "NOTE: Traffic Server received User Sig %d from pid: %d uid: %d\n",
00182                sig, t->si_pid, t->si_uid);
00183 #endif
00184     } else {
00185       snprintf(sig_msg, sizeof(sig_msg), "NOTE: Traffic Server received Kernel Sig %d, Reason: %d\n", sig, t->si_code);
00186     }
00187 
00188     write(2, sig_msg, strlen(sig_msg));
00189     
00190   }
00191 #else
00192   snprintf(sig_msg, sizeof(sig_msg), "NOTE: Traffic Server received Sig %d: %s\n", sig, strsignal(sig));
00193   ATS_UNUSED_RETURN(write(2, sig_msg, strlen(sig_msg)));
00194   
00195 #endif
00196 
00197 #if TS_HAS_PROFILER
00198   ProfilerStop();
00199 #endif
00200   shutdown_system();
00201 
00202   
00203   
00204   switch (sig) {
00205   case SIGQUIT:
00206   case SIGILL:
00207   case SIGTRAP:
00208 #if !defined(linux)
00209   case SIGEMT:
00210   case SIGSYS:
00211 #endif
00212   case SIGFPE:
00213   case SIGBUS:
00214   case SIGXCPU:
00215   case SIGXFSZ:
00216   case SIGSEGV:
00217     ink_stack_trace_dump();
00218     signal(sig, SIG_DFL);
00219     return;
00220   case SIGUSR2:
00221     ink_stack_trace_dump();
00222     return;
00223   case SIGABRT:
00224   case SIGUSR1:
00225   default:
00226     _exit(sig);
00227   }
00228 }
00229 
00230 static void
00231 child_signal_handler(int sig)
00232 {
00233   (void) sig;
00234   int pid;
00235   int saved_errno = errno;
00236   while ((pid = waitpid(-1, 0, WNOHANG)) > 0) {
00237     fprintf(stderr, "child %d exited\n", pid);
00238     ++exited_children;
00239   }
00240   errno = saved_errno;
00241 }
00242 
00243 static void
00244 set_signal(int signal, SigActionFunc_t action_func)
00245 {
00246   struct sigaction action;
00247   struct sigaction o_action;
00248 
00249 #if !defined(linux) && !defined(freebsd)
00250   action.sa_handler = NULL;
00251   action.sa_sigaction = action_func;
00252 #else
00253   action.sa_handler = action_func;
00254 #endif
00255   
00256   sigemptyset(&(action.sa_mask));       
00257   action.sa_flags = 0;
00258 
00259   int res = sigaction(signal, &action, &o_action);
00260   ink_release_assert(res == 0);
00261 }
00262 
00263 static void
00264 check_signal(int signal, SigActionFunc_t action_func)
00265 {
00266   struct sigaction action;
00267   struct sigaction o_action;
00268 
00269 #if !defined(linux) && !defined(freebsd)
00270   action.sa_handler = NULL;
00271   action.sa_sigaction = action_func;
00272   action.sa_flags = SA_SIGINFO;
00273 #else
00274   action.sa_handler = action_func;
00275   action.sa_flags = 0;
00276 #endif
00277   
00278   sigemptyset(&(action.sa_mask));       
00279 
00280   int res = sigaction(signal, &action, &o_action);
00281   ink_release_assert(res == 0);
00282 
00283 #if !defined(linux) && !defined(freebsd)
00284   if (o_action.sa_sigaction != action_func) {
00285     fprintf(stderr, "Handler for signal %d was %p, not %p as expected\n", signal, o_action.sa_sigaction, action_func);
00286   }
00287 #endif
00288 }
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 void
00297 check_signals()
00298 {
00299   check_signal(SIGPIPE, (SigActionFunc_t) SIG_IGN);
00300   check_signal(SIGQUIT, (SigActionFunc_t) signal_handler);
00301   check_signal(SIGHUP, (SigActionFunc_t) interrupt_handler);
00302   check_signal(SIGTERM, (SigActionFunc_t) signal_handler);
00303   check_signal(SIGINT, (SigActionFunc_t) signal_handler);
00304   check_signal(SIGUSR1, (SigActionFunc_t) signal_handler);
00305 }
00306 
00307 
00308 
00309 
00310 
00311 
00312 #if !defined(linux) && !defined(freebsd) && defined(DEBUG)
00313 static void *
00314 check_signal_thread(void *)
00315 {
00316   for (;;) {
00317     check_signals();
00318     sleep(2);
00319   }
00320   return NULL;
00321 }
00322 #endif
00323 
00324 void
00325 init_signals(bool do_stackdump)
00326 {
00327   sigset_t sigsToBlock;
00328 
00329   sigemptyset(&sigsToBlock);
00330   ink_thread_sigsetmask(SIG_SETMASK, &sigsToBlock, NULL);
00331 
00332   set_signal(SIGPIPE, (SigActionFunc_t) SIG_IGN);
00333   set_signal(SIGQUIT, (SigActionFunc_t) signal_handler);
00334   set_signal(SIGTERM, (SigActionFunc_t) signal_handler);
00335   set_signal(SIGINT, (SigActionFunc_t) signal_handler);
00336   set_signal(SIGHUP, (SigActionFunc_t) interrupt_handler);
00337   set_signal(SIGILL, (SigActionFunc_t) signal_handler);
00338   if(do_stackdump) {
00339     set_signal(SIGBUS, (SigActionFunc_t) signal_handler);
00340     set_signal(SIGSEGV, (SigActionFunc_t) signal_handler);
00341   }
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 #if !defined(freebsd)
00356   set_signal(SIGUSR1, (SigActionFunc_t) signal_handler);
00357 #endif
00358 
00359 #if defined(linux)
00360   set_signal(SIGUSR2, (SigActionFunc_t) signal_handler);
00361 #endif
00362 
00363 #if !defined(linux) && !defined(freebsd) && defined(DEBUG)
00364   ink_thread_create(check_signal_thread, NULL);
00365 #endif
00366 
00367   
00368   
00369 }
00370 
00371 
00372 int
00373 init_tracker(const char *config_var, RecDataT , RecData data, void * )
00374 {
00375   static Event *tracker_event = NULL;
00376   int dump_mem_info_frequency = 0;
00377 
00378   if (config_var)
00379     dump_mem_info_frequency = data.rec_int;
00380   else
00381     dump_mem_info_frequency = REC_ConfigReadInteger("proxy.config.dump_mem_info_frequency");
00382   Debug("tracker", "init_tracker called [%d]\n", dump_mem_info_frequency);
00383   if (tracker_event) {
00384     tracker_event->cancel();
00385     tracker_event = NULL;
00386   }
00387   if (dump_mem_info_frequency > 0) {
00388     tracker_event = eventProcessor.schedule_every(new TrackerContinuation,
00389                                                   HRTIME_SECONDS(dump_mem_info_frequency), ET_CALL);
00390   }
00391   return 1;
00392 }
00393 
00394 void
00395 init_signals2()
00396 {
00397   eventProcessor.schedule_every(new SignalContinuation, HRTIME_MSECOND * 500, ET_CALL);
00398   REC_RegisterConfigUpdateFunc("proxy.config.dump_mem_info_frequency", init_tracker, NULL);
00399   RecData data;
00400   data.rec_int = 0; 
00401   init_tracker(NULL, RECD_INT, data, NULL);
00402 }
00403 
00404 
00405 void
00406 init_daemon_signals()
00407 {
00408   struct sigaction act;
00409   ink_assert(signal(SIGCHLD, (VI_PFN) child_signal_handler) != SIG_ERR);
00410   act.sa_handler = (VI_PFN) child_signal_handler;
00411   ink_assert(!sigemptyset(&act.sa_mask));
00412   act.sa_flags = SA_NOCLDSTOP;
00413   ink_assert(!sigaction(SIGCHLD, &act, NULL));
00414 }