Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:717: Inside #if undefined(NO_SLOW_REQ_BT)
  protected mixed slow_be_call_out;      protected void slow_be_before_cb()   {   #ifdef DEBUG    if (this_thread() != backend_thread) error ("Run from wrong thread.\n");   #endif    if (Pike.Backend monitor = slow_be_call_out && slow_req_monitor) {    monitor->remove_call_out (slow_be_call_out);    slow_be_call_out = 0; +  +  float backend_rtime = +  (gethrtime() - thread_task_start_times[this_thread()]) / 1E6; +  thread_task_start_times[this_thread()] = 0; +  +  if (backend_rtime > slow_be_timeout) { +  report_slow_thread_finished (this_thread(), backend_rtime);    }    } -  + }      protected void slow_be_after_cb()   {    // FIXME: This should try to compensate for delays due to the pike    // gc, because it just causes noise here.   #ifdef DEBUG    if (this_thread() != backend_thread) error ("Run from wrong thread.\n");   #endif -  if (slow_be_timeout > 0.0) -  if (Pike.Backend monitor = slow_req_monitor) +  if (slow_be_timeout > 0.0) { +  if (Pike.Backend monitor = slow_req_monitor) { +  thread_task_start_times[this_thread()] = gethrtime();    slow_be_call_out = monitor->call_out (dump_slow_req, slow_be_timeout,    this_thread(), slow_be_timeout);    } -  +  } + }      void slow_req_count_changed()   {    Pike.Backend monitor = slow_req_monitor;    int count = query ("slow_req_bt_count");       if (count && monitor) {    // Just a change of the count - nothing to do.    }   
Roxen.git/server/base_server/roxen.pike:798: Inside #if undefined(NO_SLOW_REQ_BT)
   else {    Pike.DefaultBackend->before_callback = 0;    Pike.DefaultBackend->after_callback = 0;    if (Pike.Backend monitor = slow_be_call_out && slow_req_monitor) {    monitor->remove_call_out (slow_be_call_out);    slow_be_call_out = 0;    }    }   }    + protected int last_dump_hrtime; +    protected void dump_slow_req (Thread.Thread thread, float timeout)   {    object threads_disabled = _disable_threads();       int count = query ("slow_req_bt_count");    if (count > 0) set ("slow_req_bt_count", count - 1);       if (thread == backend_thread && !slow_be_call_out) {    // Avoid false alarms for the backend thread if we got here due to    // a race. Should perhaps have something like this for the handler
Roxen.git/server/base_server/roxen.pike:820: Inside #if undefined(NO_SLOW_REQ_BT)
   }       else {    string th_name =    ((thread != backend_thread) && thread_name(thread, 1)) || "";    if (sizeof(th_name))    th_name = " - " + th_name + " -";    report_debug ("###### %s 0x%x%s has been busy for more than %g seconds.\n",    thread == backend_thread ? "Backend thread" : "Thread",    thread->id_number(), th_name, timeout); -  describe_all_threads (0, threads_disabled); +  int hrnow = gethrtime(); +  if ((hrnow - last_dump_hrtime) / 1E6 < slow_req_timeout / 2) { +  describe_thread (thread); +  } else { +  last_dump_hrtime = hrnow; +  mixed err = catch { +  describe_all_threads(0, 1); +  }; +  if (err) master()->handle_error(err);    } -  +  }       threads_disabled = 0; // Paranoia.   }    -  + protected void report_slow_thread_finished (Thread.Thread thread, +  float time_spent) + { +  string th_name = +  ((thread != backend_thread) && thread_name(thread, 1)) || ""; +  if (sizeof(th_name)) +  th_name = " - " + th_name + " -"; +  +  report_debug ("###### %s 0x%x%s finished after %.2f seconds.\n", +  (thread == backend_thread ? +  "Backend thread" : "Thread"), +  thread->id_number(), th_name, time_spent); + } +    #endif // !NO_SLOW_REQ_BT      // // This is easier than when there are no threads.   // // See the discussion below. :-)   //   // // But there is extra functionality below we really want, though,   // // so let's use that one instead...   // function async_sig_start( function f, int really )   // {   // return lambda( mixed ... args ) {
Roxen.git/server/base_server/roxen.pike:948:   #endif    {    h[0](@h[1]);    }    };    int end_hrtime = gethrtime();       float handler_rtime = (end_hrtime - start_hrtime)/1E6;    thread_task_start_times[this_thread()] = 0;    + #ifndef NO_SLOW_REQ_BT +  if (slow_req_timeout > 0.0 && +  handler_rtime > slow_req_timeout) { +  report_slow_thread_finished (this_thread(), handler_rtime); +  } + #endif +     h=0;    busy_threads--;    thread_flagged_as_busy = 0;    if (handler_rtime > 0.01) handler_num_runs_001s++;    if (handler_rtime > 0.05) handler_num_runs_005s++;    if (handler_rtime > 0.15) handler_num_runs_015s++;    if (handler_rtime > 0.50) handler_num_runs_05s++;    if (handler_rtime > 1.00) handler_num_runs_1s++;    if (handler_rtime > 5.00) handler_num_runs_5s++;    if (handler_rtime > 15.00) handler_num_runs_15s++;
Roxen.git/server/base_server/roxen.pike:6278:    if (callback) p->set_done_callback(callback);    p->output(to);    if(to2) p->output(to2);    p->input(from);    return p;   #if constant(spider.shuffle)    }   #endif   }    + // Dump a single thread. + void describe_thread (Thread.Thread thread) + { +  int hrnow = gethrtime(); +  string thread_descr = ""; +  if (string th_name = thread_name(thread, 1)) +  thread_descr += " - " + th_name; +  if (int start_hrtime = thread_task_start_times[thread]) +  thread_descr += sprintf (" - busy for %.3fs", +  (hrnow - start_hrtime) / 1e6); +  report_debug(">> ### Thread 0x%x%s:\n", +  thread->id_number(), +  thread_descr); +  // Use master()->describe_backtrace to sidestep the background +  // failure wrapper that's active in RUN_SELF_TEST. +  report_debug(">> " + +  replace (master()->describe_backtrace (thread->backtrace()), +  "\n", "\n>> ") + +  "\n"); + } +    // Dump all threads to the debug log.   void describe_all_threads (void|int ignored, // Might be the signal number. -  void|object threads_disabled) +  void|int(0..1) inhibit_threads_disabled)   { -  if (!threads_disabled) +  object threads_disabled; +  if (!inhibit_threads_disabled)    // Disable all threads to avoid potential locking problems while we    // have the backtraces. It also gives an atomic view of the state.    threads_disabled = _disable_threads();       array(Thread.Thread) threads = all_threads();       report_debug("###### Describing all %d pike threads:\n>>\n",    sizeof (threads));       threads = Array.sort_array (
Roxen.git/server/base_server/roxen.pike:6304:    lambda (Thread.Thread a, Thread.Thread b) {    // Backend thread first, otherwise in id order.    if (a == backend_thread)    return 0;    else if (b == backend_thread)    return 1;    else    return a->id_number() > b->id_number();    });    -  int hrnow = gethrtime(); +     foreach (threads, Thread.Thread thread) { -  string thread_descr = ""; -  if (string th_name = thread_name(thread, 1)) -  thread_descr += " - " + th_name; -  if (int start_hrtime = thread_task_start_times[thread]) -  thread_descr += sprintf (" - busy for %.3fs", -  (hrnow - start_hrtime) / 1e6); -  report_debug(">> ### Thread 0x%x%s:\n", -  thread->id_number(), -  thread_descr); -  // Use master()->describe_backtrace to sidestep the background -  // failure wrapper that's active in RUN_SELF_TEST. -  report_debug(">> " + -  replace (master()->describe_backtrace (thread->backtrace()), -  "\n", "\n>> ") + -  "\n"); +  describe_thread (thread);    }    -  +  threads = 0; +  +  if (catch {    array(array) queue = handle_queue->peek_array();       // Ignore the handle thread shutdown marker, if any.    queue -= ({0});       if (!sizeof (queue)) -  report_debug ("###### No entries in the handler queue\n"); +  report_debug("###### No entries in the handler queue.\n");    else { -  report_debug ("###### %d entries in the handler queue:\n>>\n", +  report_debug("###### %d entries in the handler queue:\n>>\n",    sizeof (queue)); -  foreach (queue; int i; array task) -  report_debug (">> %d: %s\n", i, +  foreach(queue; int i; array task) +  report_debug(">> %d: %s\n", i,    replace (debug_format_queue_task (task), "\n", "\n>> ")); -  report_debug (">> \n"); +  report_debug(">> \n");    } -  +  queue = 0; +  }) { +  report_debug("###### Handler queue busy.\n"); +  }    -  queue = bg_queue->peek_array(); +  if (catch { +  array queue = bg_queue->peek_array();       if (!sizeof (queue))    report_debug ("###### No entries in the background_run queue\n");    else {    report_debug ("###### %d entries in the background_run queue:\n>>\n",    sizeof (queue));    foreach (queue; int i; array task)    report_debug (">> %d: %s\n", i,    replace (debug_format_queue_task (task), "\n", "\n>> "));    report_debug (">> \n");    } -  +  queue = 0; +  }) { +  report_debug("###### background_run queue busy.\n"); +  }       report_debug ("###### Thread and queue dumps done at %s\n", ctime (time()));    -  queue = 0; -  threads = 0; +     threads_disabled = 0;      #ifdef DEBUG    report_debug (RoxenDebug.report_leaks());   #endif   }         // Dump threads by file polling.