<div dir="ltr"><div>ABCL does use the native mechanism to implement interrupt-thread. The control thread receives save the interrupt-thread function, sets a flag, and then uses java's thread.interrupt on the targeted thread. The problem is that the handling of the interrupt in the targeted thread needs to be done by that thread and when the thread is busy it won't handle the interrupt. I think that's the intent including the checks for interrupt in generated code - so that it might be handled sooner. The problem is that check isn't checking the right variable.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 7, 2022 at 3:23 AM Alessio Stalla <<a href="mailto:alessiostalla@gmail.com">alessiostalla@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">To me, this looks overly complicated with all these flags. I never understood why ABCL does all this. Java threads already natively have an interrupt flag. Is there a reason for not using the native Java mechanism? <a href="https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html" target="_blank">https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html</a></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 7 Apr 2022 at 00:13, Alan Ruttenberg <<a href="mailto:alanruttenberg@gmail.com" target="_blank">alanruttenberg@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hi folks,</div><div><br></div><div>Maybe someone has a feel for how interrupts work in ABCL?</div><div><br></div><div>Doing an interrupt in ABCL from Slime doesn't interrupt until the 
end of a function or sleep or wait is called.  This means whenever I 
accidentally have a too long or infinite loop by mistake the only thing I 
can do is quit lisp and start over. <span style="font-family:monospace"><span style="font-family:arial,sans-serif">This is probably THE most irritating problem I have with ABCL. It doesn't happen often but when it does it completely disrupts work.<br></span></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif"><br></span></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">Slime handles an interrupt by calling interrupt-thread. Interrupt-thread saves the function and sets a flag. When the interrupted process next checks the flag it will call the interrupt function. </span></span>At first I thought lisp wasn't checking for an interrupt often enough, but that's not the problem. If I compile (loop for i = 1)  I get <br></div><div><br></div><div><span style="font-family:monospace">  public final LispObject execute() {<br>;         do {<br>;             if (!<span style="color:rgb(255,0,0)">Lisp.interrupted</span>) {<br>;                 continue;<br>;             }<br>;             Lisp.handleInterrupt();<br>;         } while (true);<br>;     }</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">So
 why doesn't the interrupt work? Well it seems there are two paths to 
interrupt. One is via interrupt-thread. Here is the code that sets the flag.</span><br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">    final synchronized void interrupt(LispObject function, LispObject args)<br>    {<br>        pending = new Cons(args, pending);<br>        pending = new Cons(function, pending);<br>        <span style="color:rgb(255,0,0)">threadInterrupted</span> = true;<br>        javaThread.interrupt();<br>    }</span></div><div><span style="font-family:arial,sans-serif"><br></span></div><div><span style="font-family:arial,sans-serif">Note
 that it is setting thread.threadInterrupted rather than 
Lisp.interrupted. In fact, the only way to set Lisp.interrupted is via 
Lisp.setInterrupted() and the only function that calls that is 
ext:interrupt-lisp. Nothing calls ext:interrupt-lisp. So that nice check
 within the loop is checking for a signal that currently never arrives.<br></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif"><br></span></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">The
 javathread.interrupt is only periodically detected by an explicit call or via an InterruptedException that Java will throw when the thread yields or via a check of thread.isInterrupted. The latter is checked in one place, inside a catch, 
which afaik isn't executed unless there's an error in the thread - it's 
the "Ignoring uncaught exception" path. <br></span></span></div><div><div><span style="font-family:arial,sans-serif"><br></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">Now, if
 I call ext:interrupt-lisp from the *inferior-lisp* a break comes up 
during the infinite loop and I can kill it! This is the desired behavior. </span></span></div><span style="font-family:monospace"><span style="font-family:arial,sans-serif"></span></span></div><div><span style="font-family:arial,sans-serif"><br></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">The
 problem is, I can't figure out where to call (ext:interrupt-lisp) 
within slime. I tried to put it right after interrupt-thread when that 
is called in swank::queue-thread-interrupt, which is what is eventually 
called when you hit C-c in the repl.  But that causes an error and kills
 the slime session. And emacs, for that matter, which needs to be force 
quit.</span></span></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif"><br></span></span></div><div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">I'm thinking that in the case of a control-c we should not use thread-interrupt but rather lisp interrupted. </span></span><span style="font-family:monospace"><span style="font-family:arial,sans-serif">threadInterrupted is thread local and Lisp.interrupted is a global. So 
technically the control c might not go to the right thread, since all 
threads are checking the global. But in the situation where it's locked 
in an infinite loop, there's no other thread doing anything, so the 
right thing happens. In any case I think that's probably easy to fix by setting another volatile to the thread to be interrupted.</span></span> In general one would have to worry about a race condition if there were several places that might call interrupt-lisp, but in this case it would only be called with an explicit Control-c and perhaps on a request to kill a thread from the slime threads buffer.</div><div><br></div><div>It's an open question as to whether interrupt-thread should take advantage of this as well, but that would require more care to avoid a race condition.<br></div><div><br></div><div>Any help on sorting this would be much appreciated.<br></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif"></span></span></div></div><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif"><br></span></span></div>Thanks,<br><div><font color="#888888"><div><span style="font-family:monospace"><span style="font-family:arial,sans-serif">Alan</span></span></div></font></div></div>
</blockquote></div>
</blockquote></div>