Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions tests/test_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ def test_errors(self):
with self.assertRaises(TypeError):
Store(3) # type: ignore

def test_interrupt_handle_requires_interruptable(self):
with self.assertRaises(WasmtimeError):
Store().interrupt_handle()

def test_interrupt_handle(self):
config = Config()
config.interruptable = True
store = Store(Engine(config))
store.interrupt_handle().interrupt()
config.epoch_interruption = True
engine = Engine(config)
engine.increment_epoch()
store = Store(engine)
store.set_epoch_deadline(1)

def test_interrupt_wasm(self):
config = Config()
config.interruptable = True
store = Store(Engine(config))
interrupt_handle = store.interrupt_handle()
config.epoch_interruption = True
engine = Engine(config)
store = Store(engine)

module = Module(store.engine, """
(import "" "" (func))
Expand All @@ -35,7 +33,7 @@ def test_interrupt_wasm(self):
(loop br 0))
(start 1)
""")
interrupt = Func(store, FuncType([], []), lambda: interrupt_handle.interrupt())
interrupt = Func(store, FuncType([], []), lambda: engine.increment_epoch())
with self.assertRaises(Trap):
Instance(store, module, [interrupt])

Expand Down
45 changes: 17 additions & 28 deletions wasmtime/_bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -1981,18 +1981,18 @@ def wasmtime_error_message(error: Any, message: Any) -> None:
def wasmtime_config_debug_info_set(arg0: Any, arg1: Any) -> None:
return _wasmtime_config_debug_info_set(arg0, arg1) # type: ignore

_wasmtime_config_interruptable_set = dll.wasmtime_config_interruptable_set
_wasmtime_config_interruptable_set.restype = None
_wasmtime_config_interruptable_set.argtypes = [POINTER(wasm_config_t), c_bool]
def wasmtime_config_interruptable_set(arg0: Any, arg1: Any) -> None:
return _wasmtime_config_interruptable_set(arg0, arg1) # type: ignore

_wasmtime_config_consume_fuel_set = dll.wasmtime_config_consume_fuel_set
_wasmtime_config_consume_fuel_set.restype = None
_wasmtime_config_consume_fuel_set.argtypes = [POINTER(wasm_config_t), c_bool]
def wasmtime_config_consume_fuel_set(arg0: Any, arg1: Any) -> None:
return _wasmtime_config_consume_fuel_set(arg0, arg1) # type: ignore

_wasmtime_config_epoch_interruption_set = dll.wasmtime_config_epoch_interruption_set
_wasmtime_config_epoch_interruption_set.restype = None
_wasmtime_config_epoch_interruption_set.argtypes = [POINTER(wasm_config_t), c_bool]
def wasmtime_config_epoch_interruption_set(arg0: Any, arg1: Any) -> None:
return _wasmtime_config_epoch_interruption_set(arg0, arg1) # type: ignore

_wasmtime_config_max_wasm_stack_set = dll.wasmtime_config_max_wasm_stack_set
_wasmtime_config_max_wasm_stack_set.restype = None
_wasmtime_config_max_wasm_stack_set.argtypes = [POINTER(wasm_config_t), c_size_t]
Expand Down Expand Up @@ -2095,6 +2095,12 @@ def wasmtime_config_dynamic_memory_guard_size_set(arg0: Any, arg1: Any) -> None:
def wasmtime_config_cache_config_load(arg0: Any, arg1: Any) -> pointer:
return _wasmtime_config_cache_config_load(arg0, arg1) # type: ignore

_wasmtime_engine_increment_epoch = dll.wasmtime_engine_increment_epoch
_wasmtime_engine_increment_epoch.restype = None
_wasmtime_engine_increment_epoch.argtypes = [POINTER(wasm_engine_t)]
def wasmtime_engine_increment_epoch(engine: Any) -> None:
return _wasmtime_engine_increment_epoch(engine) # type: ignore

class wasmtime_moduletype(Structure):
pass

Expand Down Expand Up @@ -2253,28 +2259,11 @@ def wasmtime_context_consume_fuel(context: Any, fuel: Any, remaining: Any) -> po
def wasmtime_context_set_wasi(context: Any, wasi: Any) -> pointer:
return _wasmtime_context_set_wasi(context, wasi) # type: ignore

class wasmtime_interrupt_handle(Structure):
pass

wasmtime_interrupt_handle_t = wasmtime_interrupt_handle

_wasmtime_interrupt_handle_new = dll.wasmtime_interrupt_handle_new
_wasmtime_interrupt_handle_new.restype = POINTER(wasmtime_interrupt_handle_t)
_wasmtime_interrupt_handle_new.argtypes = [POINTER(wasmtime_context_t)]
def wasmtime_interrupt_handle_new(context: Any) -> pointer:
return _wasmtime_interrupt_handle_new(context) # type: ignore

_wasmtime_interrupt_handle_interrupt = dll.wasmtime_interrupt_handle_interrupt
_wasmtime_interrupt_handle_interrupt.restype = None
_wasmtime_interrupt_handle_interrupt.argtypes = [POINTER(wasmtime_interrupt_handle_t)]
def wasmtime_interrupt_handle_interrupt(handle: Any) -> None:
return _wasmtime_interrupt_handle_interrupt(handle) # type: ignore

_wasmtime_interrupt_handle_delete = dll.wasmtime_interrupt_handle_delete
_wasmtime_interrupt_handle_delete.restype = None
_wasmtime_interrupt_handle_delete.argtypes = [POINTER(wasmtime_interrupt_handle_t)]
def wasmtime_interrupt_handle_delete(handle: Any) -> None:
return _wasmtime_interrupt_handle_delete(handle) # type: ignore
_wasmtime_context_set_epoch_deadline = dll.wasmtime_context_set_epoch_deadline
_wasmtime_context_set_epoch_deadline.restype = None
_wasmtime_context_set_epoch_deadline.argtypes = [POINTER(wasmtime_context_t), c_uint64]
def wasmtime_context_set_epoch_deadline(context: Any, ticks_beyond_current: Any) -> None:
return _wasmtime_context_set_epoch_deadline(context, ticks_beyond_current) # type: ignore

class wasmtime_func(Structure):
_fields_ = [
Expand Down
8 changes: 4 additions & 4 deletions wasmtime/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,17 @@ def cache(self, enabled: typing.Union[bool, str]) -> None:
raise WasmtimeError._from_ptr(error)

@setter_property
def interruptable(self, enabled: bool) -> None:
def epoch_interruption(self, enabled: bool) -> None:
"""
Configures whether wasm execution can be interrupted via interrupt
handles.
Configures whether wasm execution can be interrupted via epoch
increments.
"""

if enabled:
val = 1
else:
val = 0
ffi.wasmtime_config_interruptable_set(self._ptr, val)
ffi.wasmtime_config_epoch_interruption_set(self._ptr, val)

@setter_property
def consume_fuel(self, instances: bool) -> None:
Expand Down
3 changes: 3 additions & 0 deletions wasmtime/_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ def __init__(self, config: Config = None):
delattr(config, '_ptr')
self._ptr = ffi.wasm_engine_new_with_config(ptr)

def increment_epoch(self) -> None:
ffi.wasmtime_engine_increment_epoch(self._ptr)

def __del__(self) -> None:
if hasattr(self, '_ptr'):
ffi.wasm_engine_delete(self._ptr)
46 changes: 5 additions & 41 deletions wasmtime/_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,6 @@ def data(self) -> typing.Optional[typing.Any]:
else:
return None

def interrupt_handle(self) -> "InterruptHandle":
"""
Creates a new interrupt handle through which execution of wasm can be
interrupted.

Raises a `WasmtimeError` if this store's configuration has not been
configured to enable interruption.

For more information about this be sure to consult the Rust documentation:
https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Store.html#method.interrupt_handle
"""

return InterruptHandle(self)

def gc(self) -> None:
"""
Runs a GC over `externref` values that have been passed into this Store,
Expand Down Expand Up @@ -117,38 +103,16 @@ def set_wasi(self, wasi: "WasiConfig") -> None:
if error:
raise WasmtimeError._from_ptr(error)

def __del__(self) -> None:
if hasattr(self, '_ptr'):
ffi.wasmtime_store_delete(self._ptr)


class InterruptHandle:
"""
A handle which can be used to interrupt executing WebAssembly code, forcing
it to trap.

For more information about this be sure to consult the Rust documentation:
https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Store.html#method.interrupt_handle
"""

def __init__(self, store: Store):
if not isinstance(store, Store):
raise TypeError("expected a Store")
ptr = ffi.wasmtime_interrupt_handle_new(store._context)
if not ptr:
raise WasmtimeError("interrupts not enabled on Store")
self._ptr = ptr

def interrupt(self) -> None:
def set_epoch_deadline(self, ticks_after_current: int) -> None:
"""
Schedules an interrupt to be sent to interrupt this handle's store's
next (or current) execution of wasm code.
Configures the relative epoch deadline, after the current engine's
epoch, after which WebAssembly code will trap.
"""
ffi.wasmtime_interrupt_handle_interrupt(self._ptr)
ffi.wasmtime_context_set_epoch_deadline(self._context, ticks_after_current)

def __del__(self) -> None:
if hasattr(self, '_ptr'):
ffi.wasmtime_interrupt_handle_delete(self._ptr)
ffi.wasmtime_store_delete(self._ptr)


if typing.TYPE_CHECKING:
Expand Down