-
Alan Ruttenberg authored
What happens on interrupt ------------------------- I'm assuming there's both a worker thread(w) and a control thread(c) running. Running in thread(c) Call (interrupt-thread thread(w) function args) thread(c).interruptThread unpacks the arguments into a list It then calls thread(w).interrupt(function, args) thread(w).interrupt pushes args and fun on thread(w) thread local variable pending it then call java's interrupt() method. If things are left alone, the java interrupt mechanism will at some point throw an InterruptedException when running inside thread(w) various lispThread functions catch the InterruptedException and call processThreadInterrupts() processThreadInterrupts() then runs the functions in the thread local variable pending. There's also one check that uses the java interrupt mechanism, a call to thread.isInterrupted(). So if thread(w) notices that it's been interrupted in this way it will also call processThreadInterrupts(). BUT Java will only throw the exception when running functions like sleep or wait, so the exception won't be handled until one of those methods is called within thread(w). The call to isInterrupted() only happens once per function call. So if a function is in a loop, it could be a long time until the interrupt is handled. Meanwhile: Thread(w) is running. The compiler has thoughtfully inserted a check on a static variable Lisp.interrupted inside each iteration of a loop. If a global Lisp.interrupted get sets to true the compiler inserted code calls Lisp.handleInterupts(). BUT Lisp.interrupted is never set in the normal course of events. There's a function to set it, interruptLisp() but no one calls it. interruptLisp calls Lisp.setInterrupted() which sets Lisp.interrupted to true. The change: We add another static Lisp.threadToInterrupt. We change setInterrupted() take the boolean but also a thread that you want interrupted. We change handleInterrupts(), which used to call break() to check whether the current thread is equal to threadTointerrupt. When the current thread is thread(w), it call thread(w).processThreadInterrupts(). Then, we change interruptLisp() to call Lisp.setInterrupted() with the thread to be interrupted. We don't want to have to call interruptLisp separately. So we call setInterrupted() directly in thread(c).interruptLisp(). And we win. In slime, when you hit Control-c, it calls interrupt-thread with the function invoking the debugger. With the change, interrupt-thread gets handled promptly and the debugger is called, even if we are in an infinite loop.
9dfc5ad5