Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:652:   // // 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 ) {   // thread_create( f, @args );   // };   // } + local protected Queue low_handle_queue = Queue();   local protected Queue handle_queue = Queue(); - //! Queue of things to handle. - //! An entry consists of an array(function fp, array args) + //! Queues of things to handle. + //! + //! An entry consists of an @expr{array(function fp, array args)@}. + //! + //! @[low_handle_queue] is the queue that is used until all + //! configurations have loaded, when @[handle_queue] starts + //! getting used. + //! + //! Any entries in the @[handle_queue] are then transferred + //! to the @[low_handle_queue] (to preserve priorities), + //! and they are set to the same @[Queue] object (ie the + //! one that started life as @[low_handle_queue].      local protected int thread_reap_cnt;   //! Number of handler threads in the process of being stopped.      protected int threads_on_hold;   //! Number of handler threads on hold.      // Global variables for statistics   int handler_num_runs = 0;   int handler_num_runs_001s = 0;
Roxen.git/server/base_server/roxen.pike:728: Inside #if undefined(NO_SLOW_REQ_BT)
   int thread_flagged_as_busy;   #ifndef NO_SLOW_REQ_BT    Pike.Backend monitor;    mixed call_out;   #endif    if(q=catch {    do {   // if (!busy_threads) werror ("GC: %d\n", gc());    cache_clear_deltas();    THREAD_WERR("Handle thread ["+id+"] waiting for next event"); -  if(arrayp(h=handle_queue->read()) && h[0]) { +  if(arrayp(h = low_handle_queue->read()) && h[0]) {    THREAD_WERR(sprintf("Handle thread [%O] calling %s",    id, debug_format_queue_task (h)));    set_locale();    busy_threads++;    thread_flagged_as_busy = 1;    handler_num_runs++;       int start_hrtime = gethrtime();    thread_task_start_times[this_thread()] = start_hrtime;   
Roxen.git/server/base_server/roxen.pike:837:    report_error(sprintf("Raw error: %O\n", h[0]));    report_error(sprintf("Original raw error: %O\n", q[0]));    };    catch (q = 0);    catch (h = 0);    }    }    }   }    + //! Like @[handle()], but available before all configurations + //! have been loaded. + void low_handle(function f, mixed ... args) + { +  low_handle_queue->write(({f, args })); + } +    void handle(function f, mixed ... args)   {    handle_queue->write(({f, args }));   }      int handle_queue_length()   { -  return handle_queue->size(); +  return ((handle_queue != low_handle_queue) && low_handle_queue->size()) + +  handle_queue->size();   }      int number_of_threads;   //! The number of handler threads to run.      int busy_threads;   //! The number of currently busy threads.      protected array(object) handler_threads = ({});   //! The handler threads, the list is kept for debug reasons.    - void start_handler_threads() + protected void start_low_handler_threads()   {    if (query("numthreads") <= 1) {    set( "numthreads", 1 );    report_warning (LOC_S(1, "Starting one thread to handle requests.")+"\n");    } else {    report_notice (LOC_S(2, "Starting %d threads to handle requests.")+"\n",    query("numthreads") );    }    array(object) new_threads = ({});    for(; number_of_threads < query("numthreads"); number_of_threads++)    new_threads += ({ do_thread_create( "Handle Thread [" +    number_of_threads + "]",    handler_thread, number_of_threads ) });    handler_threads += new_threads;   }    -  + protected void transfer_handler_queue(Queue from, Queue to, int|void count) + { +  int transferred = sizeof(handle_queue); +  +  while (sizeof(handle_queue)) { +  array entry = handle_queue->read(); +  if (arrayp(entry)) { +  low_handle_queue->write(entry); +  } +  } +  +  // Some paranoia with respect to racing handle() vs start_handler_threads(). +  if (!transferred) { +  if (++count > 2) return; +  } +  +  low_handle(transfer_handler_queue, from, to, count); + } +  + void start_handler_threads() + { +  Queue handle_queue = this_program::handle_queue; +  this_program::handle_queue = low_handle_queue; +  +  transfer_handler_queue(handle_queue, low_handle_queue); + } +    protected int num_hold_messages;   protected Thread.Condition hold_wakeup_cond = Thread.Condition();   // Note: There are races in the use of this condition variable, but   // the only effect of that is that some handler thread might be   // considered hung when it's actually waiting on hold_wakeup_cond, and   // the hold/release handler threads function deal with hung threads   // anyway. The outcome would only be that release_handler_threads   // starts some extra handler thread unnecessarily.      void hold_handler_threads()
Roxen.git/server/base_server/roxen.pike:982:       // Wake up any handler threads on hold, and ensure none gets on hold    // after this.    if (Thread.Condition cond = hold_wakeup_cond) {    hold_wakeup_cond = 0;    cond->broadcast();    }       while(number_of_threads>0) {    number_of_threads--; -  handle_queue->write(0); +  low_handle_queue->write(0);    thread_reap_cnt++;    }    handler_threads = ({});       if (this_thread() != backend_thread && !backend_block_lock) {    thread_reap_cnt++;    Thread.Mutex mutex = Thread.Mutex();    backend_block_lock = mutex->lock();    call_out (lambda () {    thread_reap_cnt--;
Roxen.git/server/base_server/roxen.pike:6160:    return a->id_number() > b->id_number();    });       foreach (threads, Thread.Thread thread) {    describe_thread (thread);    }       threads = 0;       if (catch { -  array(array) queue = handle_queue->peek_array(); +  array(array) queue = low_handle_queue->peek_array();    -  +  if (handle_queue != low_handle_queue) { +  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");    else {    report_debug("###### %d entries in the handler queue:\n>>\n",    sizeof (queue));    foreach(queue; int i; array task)    report_debug(">> %d: %s\n", i,
Roxen.git/server/base_server/roxen.pike:6915:    strerror (file->errno()));    } else if (file->write(cert) != sizeof(cert)) {    rm(file_name);    report_error("Couldn't write certificate file %s: %s\n", file_name,    strerror (file->errno()));    }    }    }      #ifdef THREADS -  start_handler_threads(); - #if constant(Filesystem.Monitor.basic) -  start_fsgarb(); - #endif +  start_low_handler_threads();   #endif /* THREADS */       // Update the certificate registry before opening any ports.    // NB: Force all certificate files to be reread and reparsed.    scan_certs(1);       enable_configurations();       string pid_file = Getopt.find_option(argv, "p", "pid-file");    if (pid_file && query("permanent_uid")) rm(pid_file);
Roxen.git/server/base_server/roxen.pike:6947:    enable_configurations_modules();   #else    if( Getopt.find_option( argv, 0, "no-delayed-load" ))    enable_configurations_modules();    else    foreach( configurations, Configuration c )    if( c->query( "no_delayed_load" ) )    c->enable_all_modules();   #endif // RUN_SELF_TEST    + #ifdef THREADS +  start_handler_threads(); + #if constant(Filesystem.Monitor.basic) +  start_fsgarb(); + #endif + #endif /* THREADS */ +     start_scan_certs();    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");