Skip to main content

Interrupt handling for pyodide.

Project description

pyodide_interrupts

This is a package to allow handling of interrupts inside of Pyodide. Pyodide does not have preemptive multitasking. This package enables handling keyboard interrupts in Pyodide.

This defines one context handler check_interrupts(callback, interval) which causes callback to be called every interval instructions.

Simple Example:

>>> def callback(): print("check")
... with check_interrupts(callback, 10):
...    for i in range(50):
...       print(i, end=",")

0,1,check
2,3,4,5,6,check
7,8,9,10,11,check
12,13,14,15,16,check
17,18,19,20,21,check
22,23,24,25,26,check
27,28,29,30,31,check
32,33,34,35,36,check
37,38,39,40,41,check
42,43,44,45,46,check
47,48,49,check

Sketch of usage

In real usage, I use the following callback:

def check_for_interrupt(interrupt_buffer):
    def helper():
        if interrupt_buffer() == 0:
            return
        raise KeyboardInterrupt()
    return helper

interrupt_buffer is a javascript wrapper around a SharedArrayBuffer. On the main thread:

let uuid = uuid();
let interrupt_buffer = new Int32Array(new SharedArrayBuffer(4));
pyodide_worker.postMessage({"cmd" : "execute_python", code, interrupt_buffer, uuid});
let result = await responsePromise(uuid);
// If user cancels, write a nonzero value into our SAB, this will signal pyodide to quit execution of code.
onUserCancel(() => { interrupt_buffer[0] = 2; });

On the pyodide worker thread:

self.messages = {};
function handleExecutePython(msg){
    // Wrap interrupt buffer in a function that gets its value
    // Pyodide Python <==> Javascript bindings don't understand how to get values out of the SAB directly.
    msg.interrupt_buffer = function(){
        return msg.interrupt_buffer[0]; 
    };
    messages[msg.uuid] = msg;
    self.pyodide.globals["handle_message"](uuid);
}

and then the pyodide code:

from js import messages, postMessage
def handle_message(uuid):
    msg = dict(messages[uuid])
    del messages[uuid]
    # Here would use msg["cmd"] to look up handling in a dispatch.
    interrupt_buffer = msg["interrupt_buffer"]
    # check_for_interrupt will raise a KeyboardInterrupt if "onUserCancel" handler is executed on main thread.
    with check_interrupts(check_for_interrupt(interrupt_buffer), 10_000):
        result = run_code(code)
    postMessage({"cmd" : "execute_pyodide_result", "result" : result, "uuid" : uuid })

def run_code(code):
    # Parse code into ast, handle errors, get result out, etc here

Security requirements for SharedArrayBuffer to work

I quote from the MDN docs for SharedArrayBuffer:

As a baseline requirement, your document needs to be in a secure context.

For top-level documents, two headers will need to be set to cross-origin isolate your site:

Cross-Origin-Opener-Policy with same-origin as value (protects your origin from attackers) Cross-Origin-Embedder-Policy with require-corp as value (protects victims from your origin)

Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp

To check if cross origin isolation has been successful, you can test against the crossOriginIsolated property available to window and worker contexts

Building

To build a copy for local use, I recommend creating a virtual environment and then using pip install . in that virtual environment. To upload to pypi, we must build the package for a manylinux ABI to insure that the binaries will be compatible with most systems. The manylinux repository provides docker images with the appropriate old versions of CentOS for us to use to build these. To build, run sudo ./docker_build_wheels.sh. Warning: This will download a ~300mb docker image the first time you do it. Note that you will need to have docker installed for this to work. The resulting wheels will end up in the dist directory and will be suitable for upload to pypi.

[0.1.0] (2020-07-25)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyodide-interrupts-0.1.1.tar.gz (4.9 kB view details)

Uploaded Source

Built Distributions

File details

Details for the file pyodide-interrupts-0.1.1.tar.gz.

File metadata

  • Download URL: pyodide-interrupts-0.1.1.tar.gz
  • Upload date:
  • Size: 4.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

File hashes

Hashes for pyodide-interrupts-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b85bc38b92cd5c35dd1a5192a71495abe4cd57eadccfacbc0421fb44fb6c9e74
MD5 04fa45834292393470841f01913ca30f
BLAKE2b-256 b1c2918c52e47bf91570d9883a1c761c4d78a59cf4d1d8f8c67c25a4e164ff87

See more details on using hashes here.

File details

Details for the file pyodide_interrupts-0.1.1-cp39-cp39-manylinux1_x86_64.whl.

File metadata

  • Download URL: pyodide_interrupts-0.1.1-cp39-cp39-manylinux1_x86_64.whl
  • Upload date:
  • Size: 16.3 kB
  • Tags: CPython 3.9
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

File hashes

Hashes for pyodide_interrupts-0.1.1-cp39-cp39-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 d1f10d3be19a743ec8ffa4c74eb61aedea94387b05173fe978ffbac7cc61c122
MD5 729e655e462fae7c6caba63569f9bd6e
BLAKE2b-256 84a3ca568ca3c09d84841f0f7bcc527f3568eb63f1596d1ae829dc677ec9f60c

See more details on using hashes here.

File details

Details for the file pyodide_interrupts-0.1.1-cp38-cp38-manylinux1_x86_64.whl.

File metadata

  • Download URL: pyodide_interrupts-0.1.1-cp38-cp38-manylinux1_x86_64.whl
  • Upload date:
  • Size: 15.6 kB
  • Tags: CPython 3.8
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

File hashes

Hashes for pyodide_interrupts-0.1.1-cp38-cp38-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 33638ea97f3538885ab553a842f37bf38b2e814126da83014e03b638d4414ca4
MD5 ef446e33730f1db38e6ec3d444858651
BLAKE2b-256 3167715cc8a3e251553d9eee5880749d4a29cce49a5368d7b7e6971e8aefb39c

See more details on using hashes here.

File details

Details for the file pyodide_interrupts-0.1.1-cp37-cp37m-manylinux1_x86_64.whl.

File metadata

  • Download URL: pyodide_interrupts-0.1.1-cp37-cp37m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: CPython 3.7m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

File hashes

Hashes for pyodide_interrupts-0.1.1-cp37-cp37m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 d77d130373cf5aed9633ed21ccdcbc9ba8f86663b89f9152554d9a313ad7c3b1
MD5 8221527136837e2edf822883f5d6df84
BLAKE2b-256 479e097b6c60fc7e319577bb82431bf14720ba36d968839755d207804894e105

See more details on using hashes here.

File details

Details for the file pyodide_interrupts-0.1.1-cp36-cp36m-manylinux1_x86_64.whl.

File metadata

  • Download URL: pyodide_interrupts-0.1.1-cp36-cp36m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: CPython 3.6m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

File hashes

Hashes for pyodide_interrupts-0.1.1-cp36-cp36m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 3705a4f75e044254823f65585032470fd11f15f74ac2a02fe912f897bf8b233a
MD5 1c9f46998c4de758dc9591b6f8d1de3b
BLAKE2b-256 24fd8166238e98e32bd839e801350ae3613205eefd39e423d02e729bec35c823

See more details on using hashes here.

File details

Details for the file pyodide_interrupts-0.1.1-cp35-cp35m-manylinux1_x86_64.whl.

File metadata

  • Download URL: pyodide_interrupts-0.1.1-cp35-cp35m-manylinux1_x86_64.whl
  • Upload date:
  • Size: 14.8 kB
  • Tags: CPython 3.5m
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.47.0 CPython/3.6.7

File hashes

Hashes for pyodide_interrupts-0.1.1-cp35-cp35m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 455e143635204f5842d6eeefb19088bac4c582ec5bf40925794a5126448e2ed6
MD5 86e10dd3011676fd21eab0dc1e40df92
BLAKE2b-256 6739edee146c3602805261ceaac112bc6bef36e86d5b1aadd02a517137b7129f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page