emscripten-core / emscripten-core/emscripten
`__setitimer_js` is always included in the glue code
- 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
Assessment
This issue has not been assessed yet.