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