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 }