bytecodealliance / wasmtime-py

Python WebAssembly runtime powered by Wasmtime
https://bytecodealliance.github.io/wasmtime-py/
Apache License 2.0
381 stars 52 forks source link

bug: wasi import `sched_yield` is not defined #223

Open HarikrishnanBalagopal opened 3 months ago

HarikrishnanBalagopal commented 3 months ago

Update

Fixed by calling linker.define_wasi() https://github.com/amaranth-lang/amaranth-yosys/blob/17a79d937509c3412ffb778d55a5d6bc9c8b76d2/amaranth_yosys/__main__.py#L23

Please include a proper example of using WASI and other custom imports instead of just the bare-bones opinionated wasmtime.loader example https://github.com/bytecodealliance/wasmtime-py/blob/main/examples/loader.py

Overview

Steps to reproduce

Create a python venv and install the dependencies

$ python3 --version
Python 3.11.5

$ pip freeze
black==24.3.0
click==8.1.7
mypy-extensions==1.0.0
packaging==24.0
pathspec==0.12.1
platformdirs==4.2.0
wasmtime==19.0.0

Run this code with python3 main.py

from wasmtime import Store, Module, WasiConfig, Linker

def main():
    store = Store()
    wasi = WasiConfig()
    wasi.inherit_stdout()
    store.set_wasi(wasi)
    wasm_path = "starlark.wasm"
    with open(wasm_path, "rb") as f:
        wasm_code = f.read()
    module = Module(store.engine, wasm_code)
    linker = Linker(engine=store.engine)
    instance = linker.instantiate(store=store, module=module)
    print(instance)

if __name__ == "__main__":
    main()

The starlark.wasm file imports 20 WASI host functions starlark.wasm.zip

  (import "wasi_snapshot_preview1" "sched_yield" (func (;0;) (type 1)))
  (import "wasi_snapshot_preview1" "proc_exit" (func (;1;) (type 2)))
  (import "wasi_snapshot_preview1" "args_get" (func (;2;) (type 3)))
  (import "wasi_snapshot_preview1" "args_sizes_get" (func (;3;) (type 3)))
  (import "wasi_snapshot_preview1" "clock_time_get" (func (;4;) (type 4)))
  (import "wasi_snapshot_preview1" "environ_get" (func (;5;) (type 3)))
  (import "wasi_snapshot_preview1" "environ_sizes_get" (func (;6;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_write" (func (;7;) (type 5)))
  (import "wasi_snapshot_preview1" "random_get" (func (;8;) (type 3)))
  (import "wasi_snapshot_preview1" "poll_oneoff" (func (;9;) (type 5)))
  (import "wasi_snapshot_preview1" "fd_close" (func (;10;) (type 0)))
  (import "wasi_snapshot_preview1" "fd_read" (func (;11;) (type 5)))
  (import "wasi_snapshot_preview1" "fd_filestat_get" (func (;12;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_write" (func (;13;) (type 5)))
  (import "wasi_snapshot_preview1" "path_filestat_get" (func (;14;) (type 6)))
  (import "wasi_snapshot_preview1" "path_open" (func (;15;) (type 7)))
  (import "wasi_snapshot_preview1" "fd_fdstat_get" (func (;16;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_fdstat_set_flags" (func (;17;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_prestat_get" (func (;18;) (type 3)))
  (import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func (;19;) (type 8)))

Actual behaviour

$ python3 main.py
Traceback (most recent call last):
  File "..../test-py-wasmtime/main.py", line 17, in <module>
    main()
  File "..../test-py-wasmtime/main.py", line 13, in main
    instance = linker.instantiate(store=store, module=module)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "..../test-py-wasmtime/.venv/lib/python3.11/site-packages/wasmtime/_linker.py", line 171, in instantiate
    raise WasmtimeError._from_ptr(error)
wasmtime._error.WasmtimeError: unknown import: `wasi_snapshot_preview1::sched_yield` has not been defined

Expected behaviour

It should not throw an exception, sched_yield should be defined in the WASI imports.

The same WASM binary runs with the wasmtime CLI

$ wasmtime --version
wasmtime-cli 17.0.0 (ab5a4484e 2024-01-25)p
$ wasmtime run starlark.wasm 'main = lambda: print("hello world")'
hello world

Additional Context

OS: MacOS Sonoma 14.3.1 Platform: Apple M1 chip

alexcrichton commented 3 months ago

Thanks for the report! As I think you've found this needs a linker.define_wasi() call. Agreed the docs/examples could be better!