()
| 102 | |
| 103 | #[test] |
| 104 | fn function_interrupt_from_afar() -> wasmtime::Result<()> { |
| 105 | // Create an instance which calls an imported function on each iteration of |
| 106 | // the loop so we can count the number of loop iterations we've executed so |
| 107 | // far. |
| 108 | static HITS: AtomicUsize = AtomicUsize::new(0); |
| 109 | static STOP: AtomicBool = AtomicBool::new(false); |
| 110 | |
| 111 | let mut store = interruptible_store(); |
| 112 | let module = hugely_recursive_module(store.engine())?; |
| 113 | let func = Func::wrap(&mut store, || { |
| 114 | HITS.fetch_add(1, SeqCst); |
| 115 | }); |
| 116 | let instance = Instance::new(&mut store, &module, &[func.into()])?; |
| 117 | |
| 118 | // Use the instance's interrupt handle to wait for it to enter the loop long |
| 119 | // enough and then we signal an interrupt happens. |
| 120 | let engine = store.engine().clone(); |
| 121 | let thread = std::thread::spawn(move || { |
| 122 | while HITS.load(SeqCst) <= NUM_HITS && !STOP.load(SeqCst) { |
| 123 | // continue ... |
| 124 | } |
| 125 | engine.increment_epoch(); |
| 126 | }); |
| 127 | |
| 128 | // Enter the infinitely looping function and assert that our interrupt |
| 129 | // handle does indeed actually interrupt the function. |
| 130 | let iloop = instance.get_typed_func::<(), ()>(&mut store, "loop")?; |
| 131 | let trap = iloop.call(&mut store, ()).unwrap_err().downcast::<Trap>()?; |
| 132 | STOP.store(true, SeqCst); |
| 133 | thread.join().unwrap(); |
| 134 | assert!(HITS.load(SeqCst) > NUM_HITS); |
| 135 | assert_eq!(trap, Trap::Interrupt); |
| 136 | Ok(()) |
| 137 | } |
nothing calls this directly
no test coverage detected