_____
 ---'   __\_______
            ______)         Interruptible poke
            __)
           __)
 ---._______)

                                                      Jose E. Marchesi
                                                      March 02, 2020


Poke has loops.  It also does IO (yeah, right :D).  On one hand, this
means that Poke programs that never finish are definitely possible
(here is one: `while (1) {}') and, on the other, a Poke program acting
on an enormous amount of data may take a long time to finish,
depending on what it does.  Maybe hours, maybe even days?


So there are reasons for wanting to interrupt a running Poke program.
Since this weekend, this is as easy as pressing `Ctrl-C' in the
command line while a Poke program is running, or sending `SIGQUIT' to
it:

(poke) while (1) { }
Ctrl-C
(poke)
How does this work? First, Luca got some simple infrastructure for this in Jitter, in the form of an array called JITTER_PENDING_NOTIFICATIONS that contains a counter for every possible signal. Every time poke runs some PVM code, it temporarily installs a handler for SIGQUIT that notes the signal in the pending notifications array. How is the running program made aware of the presence of the signal? The Poke compiler generates `sync' instructions in strategic places, such as before the backward jump in loops:
(poke) fun foo = void: { while (1) {} }
(poke) .vm dis f foo
        note   <span class="string">&quot;foo&quot;</span>
$L1:
        prolog
        pushf
$L3:
        push   <span class="integer">0x1</span>
        bzi    $L10
        drop
        pushf
        popf   1
        sync
        ba     $L3
$L10:
        drop
        popf   1
        push   null
        return
        exitvm
When the `sync' instruction is executed, it checks 'JITTER_PENDING_NOTIFICATIONS', and raises a `PVM_E_SIGNAL' exception. The default signal handler handles this exception just exiting the program silently. Happy poking!