emscripten-core / emscripten-core/emscripten

`__setitimer_js` is always included in the glue code

Open
#26,038 10 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

Please include the following in your bug report:

**Version of emscripten/emsdk:**
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.22 (0f3d2e62bccf8e14497ff19e05a1202c51eb0c65)
clang version 22.0.0git (https:/github.com/llvm/llvm-project c7706d9472fe880ba1d3418919ad4185710c9559)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/va_erie/Projects/emsdk/upstream/bin
```

When compiling even the simplest library, the `__setitimer_js` function is always included in the glue code and imported into the WebAssembly module:

```js
var __setitimer_js = (which, timeout_ms) => {
// First, clear any existing timer.
if (timers[which]) {
clearTimeout(timers[which].id);
delete timers[which];
}
// A timeout of zero simply cancels the current timeout so we have nothing
// more to do.
if (!timeout_ms) return 0;
var id = setTimeout(() => {
delete timers[which];
callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now()));
}, timeout_ms);
timers[which] = {
id,
timeout_ms
};
return 0;
};

// ...

var wasmImports = {
/** @export */ c: __abort_js,
/** @export */ b: __emscripten_runtime_keepalive_clear,
/** @export */ a: __setitimer_js,
/** @export */ d: _proc_exit
};
```

This happens even if we don't call any functions that use timers, or even call libc functions at all. Simply linking to libc is sufficient to cause `__setitimer_js` to end up in the glue code.

I think this is caused by a circular dependency. The `setitimer` libc function calls `_emscripten_timeout`, which calls the JS-side `_setitimer_js`. This adds a dependency on the `_setitimer_js` function from libc.

Then on the JS side, `_setitimer_js` calls *back* into the WASM-side `_emscripten_timeout`, adding a dependency on it. Because we have a JS-side dependency on _emscripten_timeout, it cannot be DCE'd by the linker. Therefore, simply by importing libc, we end up including a bunch of timer glue code that is never actually called.

See also #22534.

---

You can reproduce this by creating some really simple C code:

```c
int add(int a, int b) {
return a + b;
}
```

And compiling it like so:

```bash
emcc \
-s MODULARIZE \
-s EXPORT_ES6 \
-s EXPORT_NAME=createAdd \
-s EXPORTED_FUNCTIONS='["_add"]' \
-s MAIN_MODULE=0 \
-s ENVIRONMENT=web \
-s MINIMAL_RUNTIME=1 \
-o add.js \
-Oz \
-flto \
--minify=0 \
--no-entry \
add.c
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.