Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WASI RuntimeError occurs when loading .wasm with import other than WASI function #286

Open
h1romas4 opened this issue Dec 15, 2021 · 6 comments

Comments

@h1romas4
Copy link

Hello.

In wasmer-js 1.0.2, WASI RuntimeError occurs when loading .wasm with import other than WASI function.
This occurs when there is an (import "module" "external".

test.wasm: test.wasm.zip

(import "module" "external" (func $_ZN11chipbx_core8external17h1c65b4913beb0195E (type $t0)))
(import "wasi_snapshot_preview1" "fd_write" (func $_ZN4wasi13lib_generated22wasi_snapshot_preview18fd_write17hf61715b32291be1dE (type $t8)))
(import "wasi_snapshot_preview1" "environ_get" (func $__imported_wasi_snapshot_preview1_environ_get (type $t4)))
(import "wasi_snapshot_preview1" "environ_sizes_get" (func $__imported_wasi_snapshot_preview1_environ_sizes_get (type $t4)))
(import "wasi_snapshot_preview1" "proc_exit" (func $__imported_wasi_snapshot_preview1_proc_exit (type $t1)))

Error message:

Error: Failed to instantiate WASI: RuntimeError: `
    at B.wbg.__wbg_new_342a24ca698edd87 (/home/hiromasa/devel/amd64/chipbx/chipbx-js/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:11276)
    at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
    at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
    at s.instantiate (/home/hiromasa/devel/amd64/chipbx/chipbx-js/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
    at file:///home/hiromasa/devel/wasm/test/src/index.mjs:18:12

test.wasm (Rust cargo build --target=wasm32-wasi --release):

fn main() {
    println!("internal: hello world!");
    unsafe { external(); }
}

#[link(wasm_import_module = "module")]
extern { fn external(); }

JavaScript (node.js):

import { init, WASI } from '@wasmer/wasi';
import * as fs from 'fs';

await init();

let wasi = new WASI({
    env: {
    },
    args: [
    ],
});

const moduleBytes = fs.readFileSync('src/test.wasm');
const module = await WebAssembly.compile(moduleBytes);
await wasi.instantiate(module, {
    'module': {
        'external': function() { console.log("external: hello world!") }
    }
});

// Run the start function
let exitCode = wasi.start();
let stdout = wasi.getStdoutString();

 // This should print "hello world (exit code: 0)"
console.log(`${stdout}(exit code: ${exitCode})`);

I think it was probably the way the imports argument was specified in wasi.instantiate.
In wasmer-python, I was able to get imports in the following way. How do I do it in wasmer-js?

Python:

import os
from wasmer import engine, wasi, Store, Module, Instance, Function
from wasmer_compiler_cranelift import Compiler

#
# import function
#
def external():
    print("external: hello world!")

# read .wasm file
__dir__ = os.path.dirname(os.path.realpath(__file__))
wasm_bytes = open(__dir__ + '/test.wasm', 'rb').read()

# setup
store = Store(engine.JIT(Compiler))
module = Module(store, wasm_bytes)

# create WASI env
wasi_version = wasi.get_version(module, strict=False)
wasi_env = \
    wasi.StateBuilder('test'). \
        map_directory('the_host_current_dir', '.'). \
        finalize()
import_object = wasi_env.generate_import_object(store, wasi_version)
external_function = Function(store, external)
# register import
import_object.register(
    "module",
    {
        "external": external_function
    }
)
# create instance
instance = Instance(module, import_object)

# start
instance.exports._start()

wasmer-python result: success

internal: hello world!
external: hello world!
@syrusakbary
Copy link
Member

Can you attach here the wasm file so I can test and do a new release?

It should be supported, so I'm not sure what's happening

@h1romas4
Copy link
Author

Yes. It is attached to the previous post. The .wasm is the link below.

test.wasm.zip

Please let me know if there is any information that is missing.
Thank you for your support.

@YuAo
Copy link

YuAo commented Apr 14, 2022

EDIT I think this is more likely #302

I can successfully run the wasm with Safari.


Having the similar issue here.

Error: Failed to instantiate WASI: RuntimeError: `
    at B.wbg.__wbg_new_342a24ca698edd87 (Library.esm.min.js:25:11042)
    at 0024ee5a:0x7c9d3
    at 0024ee5a:0x19d5a
    at s.instantiate (Library.esm.min.js:25:6735)
    at main (index.js:14:1)

However there's no imported modules with my case.

Here's my .wasm (compiled using WasmSwift), it should just print "42. hello.wasm.zip

The hello.wasm works fine with wasmer

> wasmer hello.wasm 
42

I use webpack 5, with buffer polyfill.

"devDependencies": {
    "buffer": "^6.0.3",
    "webpack": "^5.72.0",
    "webpack-cli": "^4.9.2"
  },
"dependencies": {
    "@wasmer/wasi": "^1.0.2"
}
//webpack.config.js
const path = require('path');
const webpack = require('webpack');

module.exports = {
    mode: 'development',
    //...
    externals: {
        'wasmer_wasi_js_bg.wasm': true
    },
    resolve: {
        fallback: {
            buffer: require.resolve('buffer/'),
        },
    },
    plugins: [
        new webpack.ProvidePlugin({
            Buffer: ['buffer', 'Buffer'],
        }),
    ]
};

@Wakeful-Cloud
Copy link

I'm running into this problem too with cura-engine and @wasmer/wasi V1.0.2

Output from the minified version (@wasmer/wasi)
Error: Failed to instantiate WASI: RuntimeError: `
    at B.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:11276)
    at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
    at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
    at s.instantiate (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
    at main (/root/cura-engine/wasmer.js:26:21)
Output from the unminified version (@wasmer/wasi/dist/Library.cjs)
Error: Failed to instantiate WASI: RuntimeError: `
    at imports.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:880:19)
    at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
    at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
    at WASI.instantiate (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:583:24)
    at main (/root/cura-engine/wasmer.js:26:21)

Note: the cura-engine WASM binary is quite large but I'm not sure that's what's causing this given the below reproduction. Furthermore, compiling without imported functions works fine with this library.


Minimal Reproduction

WASM Source
#include <stdio.h>
#include <stdint.h>

//Web Assembly V1 data types
typedef int32_t i32;

//Imported callback function
i32 callback(i32 num);

int main()
{
  //Print
  printf("Before\n");

  //Invoke the callback
  i32 result = callback(9+9);

  //Print
  printf("After (Result: %i)\n", result);

  return 0;
}

Note: compile with wasicc test.c -o test.wasm -Wl,--allow-undefined. Also, when I inspect the output, I see (import "env" "callback" (func $callback (type $t3))) so I'm pretty sure this is compiling correctly.

Host
//Imports
const {readFile} = require('fs/promises');
const {init, WASI} = require('@wasmer/wasi');

const main = async () =>
{
  //Initialize WASI
  await init();

  //Instantiate the WASI interface
  const wasi = new WASI({
    args: [],
    env: {},
  });

  //Read the web assembly
  const buffer = await readFile('./test.wasm');

  //Compile the web assembly
  const module = await WebAssembly.compile(new Uint8Array(buffer));

  //Instantiate the web assembly
  wasi.instantiate(module, {
    env: {
      //Callback
      callback: num =>
      {
        //Computer result
        const result = num + 5;

        //Log
        console.log(`[Callback] Invoked with ${num}, result: ${result}`);

        return result;
      }
    }
  });

  //Run the web assembly
  wasi.start();

  //Get the output
  const stdout = wasi.getStdoutString();

  //Log
  console.log(stdout);
};

main();
Output from the minified version (@wasmer/wasi)
Error: Failed to instantiate WASI: RuntimeError: `
    at B.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:11276)
    at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
    at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
    at s.instantiate (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
    at main (/root/cura-engine/test-wasmer.js:23:8)
Output from the unminified version (@wasmer/wasi/dist/Library.cjs)
Error: Failed to instantiate WASI: RuntimeError: `
    at imports.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:880:19)
    at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
    at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
    at WASI.instantiate (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:583:24)
    at main (/root/cura-engine/test-wasmer.js:23:8)

Workaround

Since this is a showstopper for me, I've resorted to using the experimental native wasi module. However, this doesn't work in the browser and many convenient APIs (eg: the virtual filesystem) aren't available.

Host
//Imports
const {readFile} = require('fs/promises');
const {WASI} = require('wasi');

const main = async () =>
{
  //Instantiate the WASI interface
  const wasi = new WASI({
    args: [],
    env: {},
  });

  //Read the web assembly
  const buffer = await readFile('./test.wasm');

  //Compile the web assembly
  const module = await WebAssembly.compile(new Uint8Array(buffer));

  //Instantiate the web assembly
  const instance = await WebAssembly.instantiate(module, {
    wasi_snapshot_preview1: wasi.wasiImport,
    env: {
      //Callback
      callback: num =>
      {
        //Computer result
        const result = num + 5;

        //Log
        console.log(`[Callback] Invoked with ${num}, result: ${result}`);

        return result;
      }
    }
  });

  //Run the web assembly
  wasi.start(instance);
};

main();

Note: run with the --experimental-wasi-unstable-preview1 flag.

Output
(node:32388) ExperimentalWarning: WASI is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Before
[Callback] Invoked with 18, result: 23
After (Result: 23)

Note: this is the expected output.

@syrusakbary
Copy link
Member

Verified that this issue is fixed with the PR upgrading to Wasmer 3.0 wasmerio/wasmer#299 (we also added a test case to make sure it remains fixed in future releases).

We'll publish a new version soon

@kevinbarabash
Copy link

kevinbarabash commented Aug 31, 2022

I have a .wasm file generated by the wasi sdk v16 via rust which makes use of wasi_snapshot_preview1 methods. Looking forward to a new release. In the meantime, I'll do a local build of @wasmer/wasi from main. Ignore this, I wasn't using the library properly. Things are working fine for me the current release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants