Branch: Tag:

2001-01-31

2001-01-31 01:06:09 by Per Hedbor <ph@opera.com>

Fixed [Bug 1056 (#1056)]

Rev: server/base_server/roxen.pike:1.619

4:   // 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.618 2001/01/31 01:01:41 per Exp $"; + constant cvs_version="$Id: roxen.pike,v 1.619 2001/01/31 01:06:09 per Exp $";      // Used when running threaded to find out which thread is the backend thread,   // for debug purposes only.
409:    * handle() stuff    */    - #ifndef THREADS - // handle function used when THREADS is not enabled. - local static void unthreaded_handle(function f, mixed ... args) - { -  f(@args); - } -  - function handle = unthreaded_handle; - #else - function handle = threaded_handle; - #endif -  - /* -  * THREADS code starts here -  */ +    #ifdef THREADS -  + // function handle = threaded_handle;      Thread do_thread_create(string id, function f, mixed ... args)   {
477: Inside #if defined(THREADS)
  {    return lambda( mixed ... args ) { thread_create( f, @args ); };   } - #else - function async_sig_start( function f, int really ) - { -  class SignalAsyncVerifier( function f ) -  { -  static int async_called; -  -  void really_call( array args ) -  { -  async_called = 0; -  f( @args ); -  } -  -  void call( mixed ... args ) -  { -  if( async_called ) -  { -  report_debug("\n\n" -  "Async calling failed for %O, calling synchronous\n", f); -  report_debug("Backtrace at time of hangup:\n%s\n", -  describe_backtrace( backtrace() )); -  f( @args ); -  return; -  } -  async_called=1; -  call_out( really_call, 0, args ); -  } -  }; -  // call_out is not really useful here, since we probably want to run -  // the signal handler immediately, not whenever the backend thread -  // is available. /per -  // -  // Calling directly like this may however lead to recursive mutex -  // lock errors. The problem cannot be solved using lock(2) since the -  // internal structures may be in an inconsistent state from the -  // previous call, and waiting for the lock probably leads to a -  // deadlock. /noring -  // -  // But on the other hand, you are not very likely to have any mutex -  // locks in an unthreaded pike, since it's quite impossible. /per -  // -  // But still, the problems with inconsistent internal states are -  // there. The API:s for many (thread safe) objects are designed to -  // only allow one (1) caller at any given time. It's a bug if this -  // restriction can be circumvented using signals. I suggest that -  // Thread.Mutex takes care of this problem in non-threaded mode. -  // / noring -  // -  // Apparantly it already did that. :-) -  // -  // I also fixed SIGHUP to be somewhat more asynchronous. -  // -  // I also added a rather small amount of magic so that it is called -  // asynchronously the first time it is received, but repeated -  // signals are not called asynchronously unless the first signal -  // handler was actually called. -  // -  // Except for the SIGQUIT signal, which dumps a backtrace. It would -  // be an excercise in futility to call that one asynchronously. -  // -  // I hope that this will solve all your problems. /per -  if( really > 0 ) -  return lambda( mixed ... args ){ call_out( f, 0, @args ); }; -  if( really < 0 ) -  return f; -  return SignalAsyncVerifier( f )->call; - } - #endif -  +    local static Queue handle_queue = Queue();   //! Queue of things to handle.   //! An entry consists of an array(function fp, array args)
602:    }   }    - local static void threaded_handle(function f, mixed ... args) + local static void handle(function f, mixed ... args)   {    handle_queue->write(({f, args }));   }
652:    }    }   } +  + #else + // handle function used when THREADS is not enabled. + local static void handle(function f, mixed ... args) + { +  f(@args); + } +  + // function handle = unthreaded_handle; +  + function async_sig_start( function f, int really ) + { +  class SignalAsyncVerifier( function f ) +  { +  static int async_called; +  +  void really_call( array args ) +  { +  async_called = 0; +  f( @args ); +  } +  +  void call( mixed ... args ) +  { +  if( async_called ) +  { +  report_debug("\n\n" +  "Async calling failed for %O, calling synchronous\n", f); +  report_debug("Backtrace at time of hangup:\n%s\n", +  describe_backtrace( backtrace() )); +  f( @args ); +  return; +  } +  async_called=1; +  call_out( really_call, 0, args ); +  } +  }; +  // call_out is not really useful here, since we probably want to run +  // the signal handler immediately, not whenever the backend thread +  // is available. /per +  // +  // Calling directly like this may however lead to recursive mutex +  // lock errors. The problem cannot be solved using lock(2) since the +  // internal structures may be in an inconsistent state from the +  // previous call, and waiting for the lock probably leads to a +  // deadlock. /noring +  // +  // But on the other hand, you are not very likely to have any mutex +  // locks in an unthreaded pike, since it's quite impossible. /per +  // +  // But still, the problems with inconsistent internal states are +  // there. The API:s for many (thread safe) objects are designed to +  // only allow one (1) caller at any given time. It's a bug if this +  // restriction can be circumvented using signals. I suggest that +  // Thread.Mutex takes care of this problem in non-threaded mode. +  // / noring +  // +  // Apparantly it already did that. :-) +  // +  // I also fixed SIGHUP to be somewhat more asynchronous. +  // +  // I also added a rather small amount of magic so that it is called +  // asynchronously the first time it is received, but repeated +  // signals are not called asynchronously unless the first signal +  // handler was actually called. +  // +  // Except for the SIGQUIT signal, which dumps a backtrace. It would +  // be an excercise in futility to call that one asynchronously. +  // +  // I hope that this will solve all your problems. /per +  if( really > 0 ) +  return lambda( mixed ... args ){ call_out( f, 0, @args ); }; +  if( really < 0 ) +  return f; +  return SignalAsyncVerifier( f )->call; + }   #endif /* THREADS */