_____ ---' __\_______ ______) 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 "foo" $L1: prolog pushf $L3: push 0x1 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!