Interruptible poke
[02-03-2020]

by Jose E. Marchesi

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!

Back to Applied Pokology Follow up in the mailing list...