_____
 ---'   __\_______
            ______)         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!