Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:502:    master()->handle_error (err);   #endif    roxenloader.real_exit( exit_code ); // Now we die...   }      private int shutdown_recurse;      // Shutdown Roxen   // exit_code = 0 True shutdown   // exit_code = -1 Restart - private void low_shutdown(int exit_code) + private void low_shutdown(int exit_code, int|void apply_patches)   {    if(shutdown_recurse >= 4)    {    if (mixed err =    catch (report_notice("Exiting roxen (spurious signals received).\n")) ||    catch (stop_all_configurations()))    master()->handle_error (err);    // Zap some of the remaining caches.    destruct(argcache);    destruct(cache); -  stop_error_log_cleaner(); +  stop_hourly_maintenance();   #ifdef THREADS   #if constant(Filesystem.Monitor.basic)    stop_fsgarb();   #endif    if (mixed err = catch (stop_handler_threads()))    master()->handle_error (err);   #endif /* THREADS */    roxenloader.real_exit(exit_code);    }    if (shutdown_recurse++) return;      #ifndef NO_SLOW_REQ_BT    // Turn off the backend thread monitor while we're shutting down.    slow_be_timeout_changed();   #endif    -  +  if ((apply_patches || query("patch_on_restart")) > 0) { +  mixed err = catch { +  foreach(plib->file_list_imported(), mapping(string:mixed) item) { +  report_notice("Applying patch %s...\n", item->metadata->id); +  mixed err = catch { +  plib->install_patch(item->metadata->id, +  "Internal Administrator"); +  }; +  if (err) { +  report_error("Failed to install patch %s: %s\n", +  item->metadata->id, +  describe_backtrace(err)); +  } +  } +  }; +  if (err) { +  master()->handle_error(err); +  } +  } +     if (mixed err = catch(stop_all_configurations()))    master()->handle_error (err);      #ifdef SNMP_AGENT    if(objectp(snmpagent)) {    snmpagent->stop_trap();    snmpagent->disable();    }   #endif       call_out(really_low_shutdown, 0.1, exit_code);   }      private int shutdown_started;      // Perhaps somewhat misnamed, really... This function will close all   // listen ports and then quit. The 'start' script should then start a   // new copy of roxen automatically. - void restart(float|void i, void|int exit_code) + void restart(float|void i, void|int exit_code, void|int apply_patches)   //! Restart roxen, if the start script is running   {    shutdown_started = 1; -  call_out(low_shutdown, i, exit_code || -1); +  call_out(low_shutdown, i, exit_code || -1, apply_patches);   }    - void shutdown(float|void i) + void shutdown(float|void i, void|int apply_patches)   //! Shut down roxen   {    shutdown_started = 1; -  call_out(low_shutdown, i, 0); +  call_out(low_shutdown, i, 0, apply_patches);   }      void exit_when_done()   {    shutdown_started = 1;    report_notice("Interrupt request received.\n"); -  low_shutdown(-1); +  low_shutdown(-1, -1);   }      int is_shutting_down()   //! Returns true if Roxen is shutting down.   {    return shutdown_started;   }         /*
Roxen.git/server/base_server/roxen.pike:3219:    if( conf )    {    if( conf->error_log )    conf->error_log[log_index] += ({ log_time });    }       if(errtype >= 1)    report_debug( s );   }    - protected BackgroundProcess error_log_cleaner_process; + protected BackgroundProcess hourly_maintenance_process;      protected void clean_error_log(mapping(string:array(int)) log,    mapping(string:int) cutoffs)   {    if (!log || !sizeof(log)) return;    foreach(cutoffs; string prefix; int cutoff) {    foreach(log; string key; array(int) times) {    if (!has_prefix(key, prefix)) continue;    int sz = sizeof(times);    times = filter(times, `>=, cutoff);
Roxen.git/server/base_server/roxen.pike:3261:    // Then all configurations and modules.    foreach(configurations, Configuration conf) {    clean_error_log(conf->error_log, cutoffs);       foreach(indices(conf->otomod), RoxenModule mod) {    clean_error_log(mod->error_log, cutoffs);    }    }   }    - protected void start_error_log_cleaner() + protected void patcher_report_notice(string msg, mixed ... args)   { -  if (error_log_cleaner_process) return; +  if (sizeof(args)) msg = sprintf(msg, @args); +  report_notice(RoxenPatch.wash_output(msg)); + }    -  // Clean the error log once every hour. -  error_log_cleaner_process = BackgroundProcess(3600, error_log_cleaner); + protected void patcher_report_error(string msg, mixed ... args) + { +  if (sizeof(args)) msg = sprintf(msg, @args); +  report_error(RoxenPatch.wash_output(msg));   }    - protected void stop_error_log_cleaner() + RoxenPatch.Patcher plib = +  RoxenPatch.Patcher(patcher_report_notice, patcher_report_error, +  getcwd(), getenv("LOCALDIR")); +  + protected void hourly_maintenance()   { -  if (error_log_cleaner_process) { -  error_log_cleaner_process->stop(); -  error_log_cleaner_process = UNDEFINED; +  error_log_cleaner(); +  +  if (query("auto_fetch_rxps")) { +  plib->import_file_http();    }   }    -  + protected void start_hourly_maintenance() + { +  if (hourly_maintenance_process) return; +  +  // Start a background process that performs maintenance tasks every hour +  // (eg cleaning the error log). +  hourly_maintenance_process = BackgroundProcess(3600, hourly_maintenance); + } +  + protected void stop_hourly_maintenance() + { +  if (hourly_maintenance_process) { +  hourly_maintenance_process->stop(); +  hourly_maintenance_process = UNDEFINED; +  } + } +    // When was Roxen started?   int boot_time =time();   int start_time =time();      string version()   {   #ifndef NSERIOUS    return query("default_ident")?real_version:query("ident");   #else    multiset choices=(<>);
Roxen.git/server/base_server/roxen.pike:3381: Inside #if undefined(__NT__)
     #ifndef __NT__   protected int abs_started;   protected int handlers_alive;      protected void low_engage_abs()   {    report_debug("**** %s: ABS exiting roxen!\n\n",    ctime(time()) - "\n");    _exit(1); // It might not quit correctly otherwise, if it's -  // locked up +  // locked up. Note that this also inhibits the delay +  // caused by the possible automatic installation of +  // any pending patches.   }      protected void engage_abs(int n)   {    if (!query("abs_engage")) {    abs_started = 0;    report_debug("Anti-Block System Disabled.\n");    return;    }    report_debug("**** %s: ABS engaged!\n"
Roxen.git/server/base_server/roxen.pike:5915:   protected class GCTimestamp   {    array self_ref;    protected void create() {self_ref = ({this_object()});}    protected void destroy() {    werror ("GC runs at %s", ctime(time()));    GCTimestamp();    }   }    + protected int gc_start;    -  + protected mapping(string:int) gc_histogram = ([]); +    array argv;   int main(int argc, array tmp)   {    // __builtin.gc_parameters((["enabled": 0]));    argv = tmp;    tmp = 0;      #if 0    Thread.thread_create (lambda () {    while (1) {    sleep (10);    describe_all_threads();    }    });   #endif      #ifdef LOG_GC_TIMESTAMPS -  +  Pike.gc_parameters(([ "pre_cb": lambda() { +  gc_start = gethrtime(); +  werror("GC runs at %s", ctime(time())); +  }, +  "post_cb":lambda() { +  werror("GC done after %dus\n", +  gethrtime() - gc_start); +  }, +  "destruct_cb":lambda(object o) { +  gc_histogram[sprintf("%O", object_program(o))]++; +  werror("GC cyclic reference in %O.\n", +  o); +  }, +  "done_cb":lambda(int n) { +  if (!n) return; +  werror("GC zapped %d things.\n", n); +  mapping h = gc_histogram + ([]); +  if (!sizeof(h)) return; +  array i = indices(h); +  array v = values(h); +  sort(v, i); +  werror("GC histogram (accumulative):\n"); +  foreach(reverse(i)[..9], string p) { +  werror("GC: %s: %d\n", p, h[p]); +  } +  }, +  ])); +  if (!Pike.gc_parameters()->pre_cb) { +  // GC callbacks not available.    GCTimestamp(); -  +  }   #endif       // For RBF    catch(mkdir(getenv("VARDIR") || "../var"));       dbm_cached_get = master()->resolv( "DBManager.cached_get" );       dbm_cached_get( "local" )->    query( "CREATE TABLE IF NOT EXISTS "    "compiled_formats ("
Roxen.git/server/base_server/roxen.pike:6127:    c->enable_all_modules();   #endif // RUN_SELF_TEST      #ifdef THREADS    start_handler_threads();   #if constant(Filesystem.Monitor.basic)    start_fsgarb();   #endif   #endif /* THREADS */    -  start_error_log_cleaner(); +  start_hourly_maintenance();      #ifdef TEST_EUID_CHANGE    if (test_euid_change) {    Stdio.File f = Stdio.File();    if (f->open ("rootonly", "r") && f->read())    werror ("Backend thread can read rootonly\n");    else    werror ("Backend thread can't read rootonly\n");    }   #endif
Roxen.git/server/base_server/roxen.pike:7082:   //! return, only useful for 'allow'.   //!   //! 'deny' always implies a return, no futher testing is done if a   //! 'deny' match.   {    // Now, this cache is not really all that performance critical, I    // mostly coded it as a proof-of-concept, and because it was more    // fun that trying to find the bug in the image-cache at the moment.       // Note similar code in compile_log_format. -  +  if (pattern == "") +  return 0;    string kmd5 = md5( pattern );      #if !defined(HTACCESS_DEBUG) && !defined(SECURITY_PATTERN_DEBUG)    array tmp =    dbm_cached_get( "local" )    ->query("SELECT full,enc FROM compiled_formats WHERE md5=%s", kmd5 );       if( sizeof(tmp) && (tmp[0]->full == pattern) )    {    mixed err = catch {