Thread#stop

Is it possible for one thread to put another thread in a stop (or sleep)
state? (Unlike Thread.stop which stops the current thread.)

The answer is currently no (Thread#stop was removed at one point), and
Matz has said he doesn't think this should be allowed:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10733

But what about this case:

I've got a threaded app with a DRb-based remote debugging/control
interface. I want to stop all non-DRb threads when the user sends the
"stop" command. The the user (or other external process) can then send
more commands to the DRb interface and inspect stuff without those
threads running around like crazy. Then a later call to the DRb
interface can wakeup all the threads that got stopped.

I can't use Thread.critical, because the DRb interface has to stay awake
for the next request. None of the threads in the DRb group should be
stopped.

Setting the priority of the non-DRb threads very low doesn't seem to
work either--they keep running when the DRb threads are not running.

Any ideas? If Thread#stop is a bad idea, what is the right idea in this
case?

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Dňa Piatok 10 Február 2006 05:10 Joel VanderWerf napísal:

Any ideas? If Thread#stop is a bad idea, what is the right idea in this
case?

Letting threads directly play tricks on each other is more of a Q'n'D hack
than a real parallelism solution. What you're looking for sounds like a latch
construct that the user process opens and closes for the other threads. Brief
googling indicates you could use something called a read-write mutex / lock.

Maybe there's a ruby implementation out there already, if not, it should be
doable via Mutexes and Semaphores. (Do we have Semaphores in the core or
stdlib?)

David Vallner

David Vallner wrote:

Dňa Piatok 10 Február 2006 05:10 Joel VanderWerf napísal:

Any ideas? If Thread#stop is a bad idea, what is the right idea in this
case?

Letting threads directly play tricks on each other is more of a Q'n'D hack than a real parallelism solution. What you're looking for sounds like a latch construct that the user process opens and closes for the other threads. Brief googling indicates you could use something called a read-write mutex / lock.

Maybe there's a ruby implementation out there already, if not, it should be doable via Mutexes and Semaphores. (Do we have Semaphores in the core or stdlib?)

David Vallner

I agree that Thread#stop is not a good tool for writing concurrency constructs, and Thread.stop should be used instead, as it is in the implementations of Mutex et al. Thread#stop is bad because the stopped thread can be stopped in a way that the thread cannot predict or control (except that it can prevent being stopped by being in Thread.critical). But that's exactly why I want it.

Think of this as a remote debugger (in fact, it is). I need all threads to stop wherever they are except the ones being used to debug the process. If there were a Thread.critical that applied to all threads in the DRb ThreadGroup, I'd be happy.

As I understand it, a latch would not serve this purpose. A latch stops newly created threads from running until the latch is opened. In ruby this would be easy to implement using Thread.stop within the block of each thread. Then another thread can wakeup those threads as needed:

   th = Thread.new { Thread.stop; do_some_work }
   prepare_for_th_to_run
   th.wakeup

···

--
        vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Dňa Piatok 10 Február 2006 21:29 Joel VanderWerf napísal:

As I understand it, a latch would not serve this purpose. A latch stops
newly created threads from running until the latch is opened. In ruby
this would be easy to implement using Thread.stop within the block of
each thread. Then another thread can wakeup those threads as needed:

   th = Thread.new { Thread.stop; do_some_work }
   prepare_for_th_to_run
   th.wakeup

For some strange reason I thought you were using looping worker threads with
short execution time. Ah well.

David Vallner

David Vallner wrote:

Dňa Piatok 10 Február 2006 21:29 Joel VanderWerf napísal:

As I understand it, a latch would not serve this purpose. A latch stops
newly created threads from running until the latch is opened. In ruby
this would be easy to implement using Thread.stop within the block of
each thread. Then another thread can wakeup those threads as needed:

   th = Thread.new { Thread.stop; do_some_work }
   prepare_for_th_to_run
   th.wakeup

For some strange reason I thought you were using looping worker threads with
short execution time. Ah well.

Well, some are fairly short lived, but those ones are fired off by some
"permathreads". In fact, the are so perma that they have a big rescue
clause with a retry (for StandardErrors) around everything they do.

Still wish I knew how to "freeze frame" all the threads, except the drb
threads that are inspecting them...

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Dňa Nedeľa 12 Február 2006 08:46 Joel VanderWerf napísal:

David Vallner wrote:
Well, some are fairly short lived, but those ones are fired off by some
"permathreads". In fact, the are so perma that they have a big rescue
clause with a retry (for StandardErrors) around everything they do.

Still wish I knew how to "freeze frame" all the threads, except the drb
threads that are inspecting them...

Do those "permathreads" spend a lot of time in an inconsistent state when it
would be dangerous to stop them? I'm still wondering about the latch
solution, you could possibly sprinkle those long running threads with waits
on the DRb latch to emulate stopping the threadgroup. Of course, that might
end up looking really, really ugly with remote debugging code all over your
logic. Or would this be unviable due to application responsivity?

David Vallner