emscripten-core / emscripten-core/emscripten
Problems calling main / imported functions with Node environment [EAGAIN exception]
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
Hello,
I am trying to build a [wasm version of the cvc5 application](https://github.com/netolcc06/cvc5/tree/wasm-build) using Emscripten 3.1.18. I have two main objectives:
- To generate a web page that uses the wasm and Javascript files generated by Emscripten
- To create a TypeScript API using functions exported by Emscripten
Currently I am trying to export the main function only, but I am having issues to call it implicitly passing arguments to the Module or calling cwrap/ccall. The flags I used:
`-s MODULARIZE -s EXPORTED_RUNTIME_METHODS=ccall,cwrap -s ENVIRONMENT=node -s EXPORTED_FUNCTIONS=_main -s INVOKE_RUN=1 -s EXIT_RUNTIME=0 -s INCOMING_MODULE_JS_API=arguments'`
For comparison purposes, if I generate a html page without the `-s MODULARIZE`, I can see that the input I am passing to the page is being used by the `get_char` function and the application works as intended. For instance, in the end you can see the sat/unsat result for the operation (check-sat).


However, I couldn't make it to work with the Node version. Things I've tried:
- Passing the input to the module with something like:
index.js
```
var m = require('../cvc5.js')
let input = '(set-logic QF_LRA)\
(declare-fun x () Real)\
(declare-fun y () Real)\
(declare-fun z () Real)\
(assert (= z 0))\
(assert (= (* 3 x) y))\
(assert (= (+ 1 (* 5 x)) y))\
(assert (= (+ 7 (* 4 x)) y))\
(check-sat)';
m({
"input": input
})
```
cvc5.js
```
var TTY = {
ttys: [],
init: function () {},
shutdown: function () {},
register: function (dev, ops) {
TTY.ttys[dev] = {
input: [Module["input"]],
output: [],
ops: ops
};
FS.registerDevice(dev, TTY.stream_ops)
},
...
```
or directly in the get_char
```
default_tty_ops: {
get_char: function (tty) {
if (!tty.input.length) {
var result = Module["input"];
if (ENVIRONMENT_IS_NODE) {
console.log("input 1")
var BUFSIZE = 256;
...
```
In both cases I get the exception `EAGAIN: resource temporarily unavailable, read` which is thrown and caught at the `get_char` function. Program still exits with 0.
- Calling `ccall` and `cwrap` function, which leads me to have the same exception being thrown (for the ccall it throws another exception in the end: RuntimeError: memory access out of bounds):
```
var m = require('../cvc5.js')
// argc = 2
// argv = path to a file containing the content I was passing directly as input in the previous method.
m().then((instance) => {
instance.cwrap('main', 'number', [2, arg])
instance.ccall('main', 'number' , ['number', 'string'], [2, arg])
})
```
I also tried:
```
f = instance.cwrap('main', 'number', ['number', 'array'])
f([3, ['node', 'index.js', input]])
```
With that said, my questions are:
- What is the proper way of calling main?
- Why do I get the EAGAIN exception? What is the proper way of passing input/arguments with those approaches (importing the Module or calling `ccall`/`cwrap`)?
Contributor guide
Assessment
This issue has not been assessed yet.