Interrupting repl in Slime

Alan Ruttenberg alanruttenberg at gmail.com
Mon Apr 11 02:32:16 UTC 2022


Ok, I think I cracked it. Check out
https://github.com/armedbear/abcl/pull/482
Alan


On Thu, Apr 7, 2022 at 9:26 PM Alan Ruttenberg <alanruttenberg at gmail.com>
wrote:

>
> Some more: This is where the code for checking for interrupt is generated
> (defun maybe-generate-interrupt-check ()
>   (unless (> *speed* *safety*)
>     (let ((label1 (gensym)))
>
> * (emit-getstatic +lisp+ "interrupted" :boolean)      (emit 'ifeq label1)*
>       (emit-invokestatic +lisp+ "handleInterrupt" nil nil)
>       (label label1))))
>
> I'm thinking, since interrupt-lisp isn't used anyways, modify it to take a
> thread argument.
> In interrupt-lisp, call setInterrupted with that thread.
> In Lisp.java change the type of interrupted and change setInterrupted to
> take a thread argument, setting Lisp.interrupted to it.
>
> Then, in the maybe-generate-interrupt-check don't Lisp.interrupted check
> as boolean, check if eq to current thread. The current thread can be made
> accessible adding  (ensure-thread-var-initialized), which puts it into a
> local at the beginning of the function. Access it with  (aload *thread*)
> which puts it on the stack. I think this means that the lines underlined
> above get replaced with.
>
>   (ensure-thread-var-initialized)
>   (emit-getstatic +lisp+ "interrupted" +lisp-thread+)
>   (aload *thread*)
>   (emit 'if_acmpne label1)
>
> In Lisp.handleInterrupts it's setInterrupted(null) vs
> setInterrrupted(false);
>
> As stated, this mechanism is strictly to enable control-c.
>
> However, maybe we could have it help thread-interrupt respond more
> quickly.  in Lisp.handleInterrupts.
> check thread.isInterrupted and call processThreadInterrupts (the thing
> that is done now) otherwise break.
> Have the implementation of thread-interrupt do what it does now and also
> call interrupt-lisp to get it noticed.
> ---
>
> I haven't tried this. Mostly I'm fumbling around trying to get enough
> information to do this. I don't know java byte code except what I learned
> researching this.
> I don't know if there are pitfalls. I don't know why something like this
> wouldn't have been done in the first place.
>
> The only thing I can currently think of is that there could be a race
> condition on setting Lisp.interrupted.
> The consequence of that is that if there were two quick thread-interrupts,
> only one of the threads would
> do the quick response. The other would be processed in the way it
> currently is.
>
> Anyways, comments solicited.
> Alan
>
>
>
>
>
> On Thu, Apr 7, 2022 at 1:21 PM Alan Ruttenberg <alanruttenberg at gmail.com>
> wrote:
>
>> The functions that ABCL uses in Threads.java are thread.interrupt and
>> thread.isInterrupted. It overrides interrupt and isInterrupted to implement
>> interrupt-thread - by saving away the function the target thread is to be
>> interrupted with.  Remember, interrupt-thread isn't executed by the thread
>> to be interrupted, it's called from another thread. The receiving thread
>> handles InterruptedException, which is only called on explicit check of
>> interrupt state or from sleep or wait.
>>
>> Separately, in Lisp.Java there's setInterrupted and handleInterrupt that
>> don't use the java mechanism. Rather setInterrupted sets a static volatile
>> Lisp.interrupted, handleInterrupted clears the variable and calls break.
>> setInterrupted, as I said, is only called from interrupt-lisp. Code
>> generation inserts checks of Lisp.interrupted and calls handleInterrupted
>> if it is set. I have a feeling that this part was done so that frequent
>> interrupt checks could be made without taking the performance hit of a
>> synchronized method call. Remember this check is done inside every loop
>> iteration. The check for Lisp.interrupted is a volatile read, which in most
>> cases is handled in the cache. A write to the volatile invalidates the
>> cache forcing the new value to be read from memory. So much less expensive.
>>
>> It would be useful to know the history of how it came to be that there
>> are two different interrupt mechanisms.
>>
>>
>>
>> On Thu, Apr 7, 2022 at 7:21 AM Alessio Stalla <alessiostalla at gmail.com>
>> wrote:
>>
>>> No, I mean
>>> https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupted--
>>>
>>> The only deprecated methods are suspend, resume and stop. The interrupt
>>> machinery is what developers are supposed to use (at least when not using
>>> some higher-level framework). It's a form of cooperative multitasking,
>>> since a thread can completely ignore the interrupt. However, given we have
>>> control over Lisp threads, we can play nice with that convention, and maybe
>>> offer a without-interrupts special form for performance-critical code where
>>> the developer assumes the responsibility of checking for interrupts in
>>> selected moments.
>>>
>>> On Thu, 7 Apr 2022 at 11:42, Mark Evenson <evenson at panix.com> wrote:
>>>
>>>>
>>>>
>>>> > On Apr 7, 2022, at 08:22, Alessio Stalla <alessiostalla at gmail.com>
>>>> wrote:
>>>> >
>>>> > […] Java threads already natively have an interrupt flag.
>>>>
>>>> Presumably, the [Thread.State enumeration] is what you are referring
>>>> to. I have checked that it is present in openjdk{8,11,17}, and not marked
>>>> as deprecated.
>>>>
>>>> [1]:
>>>> https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html
>>>>
>>>> --
>>>> "A screaming comes across the sky.  It has happened before but there is
>>>> nothing
>>>> to compare to it now."
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/armedbear-devel/attachments/20220410/81f8a511/attachment.html>


More information about the armedbear-devel mailing list