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.      int(0..1) handler_threads_available()   {    return sizeof(handler_threads) && 1;   }    - 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:987:       // 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:6165:    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:6919:    report_error("Couldn't create certificate file %s: %s\n", file_name,    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_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);       set_u_and_gid(); // Running with the right [e]uid:[e]gid from this point on.