2008-09-29
2008-09-29 15:57:33 by Martin Stjernholm <mast@lysator.liu.se>
-
f931d75d0f571d93caeab55769a5b12ca8647104
(145 lines)
(+110/-35)
[
Show
| Annotate
]
Branch: 5.2
Extended the slow request monitor to the backend thread. Note that this
requires a cvs fresh pike 7.8.
Also removed some old code for pikes without any thread support.
Rev: server/base_server/global_variables.pike:1.114
Rev: server/base_server/roxen.pike:1.991
6:
// Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others.
// ABS and suicide systems contributed freely by Francesco Chemolli
- constant cvs_version="$Id: roxen.pike,v 1.990 2008/09/25 21:38:11 mast Exp $";
+ constant cvs_version="$Id: roxen.pike,v 1.991 2008/09/29 15:57:33 mast Exp $";
//! @appears roxen
//!
471:
roxenloader.real_exit( exit_code ); // Now we die...
}
- private int _recurse;
+ private int shutdown_recurse;
// Shutdown Roxen
// exit_code = 0 True shutdown
// exit_code = -1 Restart
private void low_shutdown(int exit_code)
{
- if(_recurse >= 4)
+ if(shutdown_recurse >= 4)
{
if (mixed err =
catch (report_notice("Exiting roxen (spurious signals received).\n")) ||
491:
#endif /* THREADS */
roxenloader.real_exit(exit_code);
}
- if (_recurse++) return;
+ if (shutdown_recurse++) return;
-
+ // Turn off the backend thread monitor while we're shutting down.
+ slow_be_timeout_changed();
+
if (mixed err = catch(stop_all_configurations()))
werror (describe_backtrace (err));
611: Inside #if defined(THREADS) and #if undefined(NO_SLOW_REQ_BT)
// longer than a configurable timeout.
protected Pike.Backend slow_req_monitor; // Set iff slow req bt is enabled.
- protected float slow_req_timeout;
+ protected float slow_req_timeout, slow_be_timeout;
protected void slow_req_monitor_thread (Pike.Backend my_monitor)
{
621: Inside #if defined(THREADS) and #if undefined(NO_SLOW_REQ_BT)
slow_req_monitor (3600);
}
+ 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;
+ }
+ }
+
+ protected void slow_be_after_cb()
+ {
+ #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)
+ 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;
634: Inside #if defined(THREADS) and #if undefined(NO_SLOW_REQ_BT)
monitor = slow_req_monitor = Pike.SmallBackend();
Thread.thread_create (slow_req_monitor_thread, monitor);
monitor->call_out (lambda () {}, 0); // Safeguard if there's a race.
+ slow_be_timeout_changed();
}
else if (monitor) { // Stop.
slow_req_monitor = 0;
monitor->call_out (lambda () {}, 0); // To wake up the thread.
-
+ slow_be_timeout_changed();
}
}
650: Inside #if defined(THREADS) and #if undefined(NO_SLOW_REQ_BT)
slow_req_timeout = query ("slow_req_bt_timeout");
}
+ void slow_be_timeout_changed()
+ {
+ #ifdef DEBUG
+ if (query ("slow_be_bt_timeout") < 0) error ("Invalid timeout.\n");
+ #endif
+ slow_be_timeout = query ("slow_be_bt_timeout");
+
+ #ifdef DEBUG
+ if ((Pike.DefaultBackend->before_callback &&
+ Pike.DefaultBackend->before_callback != slow_be_before_cb) ||
+ (Pike.DefaultBackend->after_callback &&
+ Pike.DefaultBackend->after_callback != slow_be_after_cb))
+ werror ("Pike.DefaultBackend already hooked up with "
+ "other before/after callbacks - they get overwritten: %O/%O\n",
+ Pike.DefaultBackend->before_callback,
+ Pike.DefaultBackend->after_callback);
+ #endif
+
+ if (query ("slow_req_bt_count") && slow_be_timeout > 0.0 &&
+ // Don't trig if we're shutting down.
+ !shutdown_recurse) {
+ Pike.DefaultBackend->before_callback = slow_be_before_cb;
+ Pike.DefaultBackend->after_callback = slow_be_after_cb;
+ }
+ 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 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);
- report_debug ("###### Thread 0x%x has been busy for more than %g seconds.\n",
+ 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
+ // threads too, but otoh races are more rare there due to the
+ // longer timeouts.
+ }
+
+ else {
+ report_debug ("###### %s 0x%x has been busy for more than %g seconds.\n",
+ thread == backend_thread ? "Backend thread" : "Thread",
thread->id_number(), timeout);
- describe_all_threads();
+ describe_all_threads (threads_disabled);
}
-
+ threads_disabled = 0; // Paranoia.
+ }
+
#endif // !NO_SLOW_REQ_BT
// // This is easier than when there are no threads.
705: Inside #if defined(THREADS)
{
int thread_flagged_as_busy;
#ifndef NO_SLOW_REQ_BT
- mixed slow_req_call_out;
+ Pike.Backend monitor;
+ mixed call_out;
#endif
if(q=catch {
do {
720: Inside #if defined(THREADS)
thread_flagged_as_busy = 1;
#ifndef NO_SLOW_REQ_BT
- if (Pike.Backend monitor =
+ if (h[0] != bg_process_queue &&
// Leave out bg_process_queue. It makes a timeout on
// every individual job instead.
- h[0] != bg_process_queue &&
- slow_req_monitor) {
- slow_req_call_out =
- monitor->call_out (dump_slow_req, slow_req_timeout,
+ (monitor = slow_req_monitor) && slow_req_timeout > 0.0) {
+ call_out = monitor->call_out (dump_slow_req, slow_req_timeout,
this_thread(), slow_req_timeout);
h[0](@h[1]);
- monitor->remove_call_out (slow_req_call_out);
+ monitor->remove_call_out (call_out);
}
else
#endif
772: Inside #if defined(THREADS)
if (thread_flagged_as_busy)
busy_threads--;
#ifndef NO_SLOW_REQ_BT
- if (Pike.Backend monitor = slow_req_call_out && slow_req_monitor)
- monitor->remove_call_out (slow_req_call_out);
+ if (call_out) monitor->remove_call_out (call_out);
#endif
if (h = catch {
report_error(/*LOCALE("", "Uncaught error in handler thread: %s"
1069: Inside #if defined(THREADS)
min (time() - bg_last_busy, bg_time_buffer_max) * (int) (1 / 0.04);
#ifndef NO_SLOW_REQ_BT
- mixed slow_req_call_out;
+ Pike.Backend monitor;
+ mixed call_out;
#endif
if (mixed err = catch {
1104: Inside #if defined(THREADS)
float task_vtime, task_rtime;
#ifndef NO_SLOW_REQ_BT
- if (Pike.Backend monitor = slow_req_monitor) {
- slow_req_call_out =
- monitor->call_out (dump_slow_req, slow_req_timeout,
+ if ((monitor = slow_req_monitor) && slow_req_timeout > 0.0) {
+ call_out = monitor->call_out (dump_slow_req, slow_req_timeout,
this_thread(), slow_req_timeout);
#endif
int start_hrtime = gethrtime (1);
1118: Inside #if defined(THREADS)
};
task_rtime = (gethrtime (1) - start_hrtime) / 1e9;
#ifndef NO_SLOW_REQ_BT
- monitor->remove_call_out (slow_req_call_out);
+ monitor->remove_call_out (call_out);
}
#endif
1153: Inside #if defined(THREADS)
}
}) {
#ifndef NO_SLOW_REQ_BT
- if (Pike.Backend monitor = slow_req_call_out && slow_req_monitor)
- monitor->remove_call_out (slow_req_call_out);
+ if (call_out) monitor->remove_call_out (call_out);
#endif
bg_process_running = 0;
handle (bg_process_queue);
4980:
}
// Dump all threads to the debug log.
- void describe_all_threads()
+ void describe_all_threads (void|object threads_disabled)
{
- #if constant (thread_create)
+ if (!threads_disabled)
// Disable all threads to avoid potential locking problems while we
// have the backtraces. It also gives an atomic view of the state.
- object threads_disabled = _disable_threads();
+ threads_disabled = _disable_threads();
report_debug("###### Describing all Pike threads:\n>>\n");
5023:
threads = 0;
threads_disabled = 0;
- #else
- report_debug("Describing single thread:\n%s\n\n",
- describe_backtrace (backtrace()));
- #endif
+
#ifdef DEBUG
report_debug (RoxenDebug.report_leaks());
5354:
cdt_changed (getvar ("dump_threads_by_file"));
}
+ slow_req_count_changed();
+ slow_req_timeout_changed();
+ slow_be_timeout_changed();
+
#ifdef ROXEN_DEBUG_MEMORY_TRACE
restart_roxen_debug_memory_trace();
#endif