cplusplus.zip
generated_wit_00000.wit.zip
generated_wit_00000b.wit.zip
python.zip
world0-pvwxtgtmlk_fromPython.wasm.zip
world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm.zip
world1-consumer_fromC++.wasm.zip
Summary
Generate C++ glue code via wit-bindgen, then generate a Wasm component.
When executed, both wasmtime and jco crash.
It may be caused by the glue code generated by wit-bindgen causing resource dropped multiple times.
Environment
jco 1.16.1
wasmtime 41.0.0
wit-bindgen 0.51.0
OS: macOS Sequoia 15.7
CPU: Intel Core i7
Reproduce steps
The specific reproduction steps are as follows:
-
Use the following command to generate Python binding files from generated_wit_00000.wit.
componentize-py -d xxx/witfiles/package3hl16smu1p -w world0-pvwxtgtmlk bindings xxx/python/world0-pvwxtgtmlk
-
Implement the Python program as shown in python.zip.
-
Use the following command to generate Wasm component file from Python.
cd xxx/python/world0-pvwxtgtmlk
componentize-py --wit-path xxx/witfiles/package3hl16smu1p --world world0-pvwxtgtmlk componentize world0-pvwxtgtmlk_generated -o xxx/componentfiles/world0-pvwxtgtmlk_fromPython.wasm
-
Use the following command to generate C++ binding files from generated_wit_00000b.wit.
wit-bindgen cpp xxx/witfiles/package3hl16smu1p --world world1-consumer --out-dir xxx/cplusplus/world1-consumer
-
Implement the C++ program as shown in cplusplus.zip.
-
Use the following command to generate Wasm component file from C++.
xxx/WASI/wasi-sdk-27.0/wasi-sdk-27.0-x86_64-macos/bin/wasm32-wasip2-clang++ -std=c++23 -o xxx/componentfiles/world1-consumer_fromC++.wasm -mexec-model=reactor xxx/cplusplus/world1-consumer/world1-consumer_generated.cpp xxx/cplusplus/world1-consumer/world1_consumer.cpp xxx/cplusplus/world1-consumer/world1_consumer_component_type.o
-
Use wac to combine the two Wasm component files:
wac plug xxx/componentfiles/world1-consumer_fromC++.wasm --plug xxx/componentfiles/world0-pvwxtgtmlk_fromPython.wasm -o xxx/componentfiles/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm
-
Use wasmtime to run the final Wasm component file:
wasmtime run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm
Wasmtime prints:
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
Error: failed to run main module `world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
Caused by:
0: failed to invoke `run` function
1: error while executing at wasm backtrace:
0: 0x22813ea - world1-consumer_fromC++.wasm!mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File()
1: 0x227fdba - world1-consumer_fromC++.wasm!wit::vector<mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File>::~vector()
2: 0x227f7dd - world1-consumer_fromC++.wasm!exports::wasi::cli::run::Run()
3: 0x2281dae - world1-consumer_fromC++.wasm!__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
2: unknown handle index 5
- Use jco to run the same final Wasm component file:
jco run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm
jco prints:
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
TypeError: Invalid handle
at rscTableRemove (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:1597:13)
at trampoline165 (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:37995:23)
at world1-consumer_fromC++.wasm.mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[84]:0x2e9d)
at world1-consumer_fromC++.wasm.wit::vector<mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File>::~vector() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[36]:0x186d)
at world1-consumer_fromC++.wasm.exports::wasi::cli::run::Run() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[23]:0x1290)
at world1-consumer_fromC++.wasm.__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[103]:0x3861)
at fn (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38984:15)
at _withGlobalCurrentTaskMeta (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:487:12)
at Object.run (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38981:15)
at file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/_run.js:14:15
Simplified reproduction steps
- Use wasmtime to run the final Wasm component file:
wasmtime run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm
Wasmtime prints:
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
Error: failed to run main module `world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
Caused by:
0: failed to invoke `run` function
1: error while executing at wasm backtrace:
0: 0x22813ea - world1-consumer_fromC++.wasm!mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File()
1: 0x227fdba - world1-consumer_fromC++.wasm!wit::vector<mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File>::~vector()
2: 0x227f7dd - world1-consumer_fromC++.wasm!exports::wasi::cli::run::Run()
3: 0x2281dae - world1-consumer_fromC++.wasm!__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
2: unknown handle index 5
- Use jco to run the same final Wasm component file:
jco run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm
jco prints:
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
TypeError: Invalid handle
at rscTableRemove (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:1597:13)
at trampoline165 (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:37995:23)
at world1-consumer_fromC++.wasm.mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[84]:0x2e9d)
at world1-consumer_fromC++.wasm.wit::vector<mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File>::~vector() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[36]:0x186d)
at world1-consumer_fromC++.wasm.exports::wasi::cli::run::Run() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[23]:0x1290)
at world1-consumer_fromC++.wasm.__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[103]:0x3861)
at fn (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38984:15)
at _withGlobalCurrentTaskMeta (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:487:12)
at Object.run (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38981:15)
at file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/_run.js:14:15
Result Analysis
It may due to:
wit-bindgen C++: list<own> imported argument is not invalidated after call, causing invalid-handle/double-drop in destructor.
When importing a function with signature drain-ids: func(xs: list<own>) -> list, generated C++ bindings map it to DrainIds(std::span xs).
After the call returns, caller-side xs elements are still destructed as if they own live handles, leading to a second drop and runtime error (unknown handle index / Invalid handle).
And when we replace C++ with Rust to implement the same logic, this bug disappers in both wasmtime and jco. So, it is not due to the Wasm runtime.
cplusplus.zip
generated_wit_00000.wit.zip
generated_wit_00000b.wit.zip
python.zip
world0-pvwxtgtmlk_fromPython.wasm.zip
world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm.zip
world1-consumer_fromC++.wasm.zip
Summary
Generate C++ glue code via wit-bindgen, then generate a Wasm component.
When executed, both wasmtime and jco crash.
It may be caused by the glue code generated by wit-bindgen causing resource dropped multiple times.
Environment
jco 1.16.1
wasmtime 41.0.0
wit-bindgen 0.51.0
OS: macOS Sequoia 15.7
CPU: Intel Core i7
Reproduce steps
The specific reproduction steps are as follows:
Use the following command to generate Python binding files from generated_wit_00000.wit.
componentize-py -d xxx/witfiles/package3hl16smu1p -w world0-pvwxtgtmlk bindings xxx/python/world0-pvwxtgtmlkImplement the Python program as shown in python.zip.
Use the following command to generate Wasm component file from Python.
cd xxx/python/world0-pvwxtgtmlkcomponentize-py --wit-path xxx/witfiles/package3hl16smu1p --world world0-pvwxtgtmlk componentize world0-pvwxtgtmlk_generated -o xxx/componentfiles/world0-pvwxtgtmlk_fromPython.wasmUse the following command to generate C++ binding files from generated_wit_00000b.wit.
wit-bindgen cpp xxx/witfiles/package3hl16smu1p --world world1-consumer --out-dir xxx/cplusplus/world1-consumerImplement the C++ program as shown in cplusplus.zip.
Use the following command to generate Wasm component file from C++.
xxx/WASI/wasi-sdk-27.0/wasi-sdk-27.0-x86_64-macos/bin/wasm32-wasip2-clang++ -std=c++23 -o xxx/componentfiles/world1-consumer_fromC++.wasm -mexec-model=reactor xxx/cplusplus/world1-consumer/world1-consumer_generated.cpp xxx/cplusplus/world1-consumer/world1_consumer.cpp xxx/cplusplus/world1-consumer/world1_consumer_component_type.oUse wac to combine the two Wasm component files:
wac plug xxx/componentfiles/world1-consumer_fromC++.wasm --plug xxx/componentfiles/world0-pvwxtgtmlk_fromPython.wasm -o xxx/componentfiles/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasmUse wasmtime to run the final Wasm component file:
wasmtime run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasmWasmtime prints:
jco run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasmjco prints:
Simplified reproduction steps
wasmtime run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasmWasmtime prints:
jco run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasmjco prints:
Result Analysis
It may due to:
wit-bindgen C++: list<own> imported argument is not invalidated after call, causing invalid-handle/double-drop in destructor.
When importing a function with signature drain-ids: func(xs: list<own>) -> list, generated C++ bindings map it to DrainIds(std::span xs).
After the call returns, caller-side xs elements are still destructed as if they own live handles, leading to a second drop and runtime error (unknown handle index / Invalid handle).
And when we replace C++ with Rust to implement the same logic, this bug disappers in both wasmtime and jco. So, it is not due to the Wasm runtime.