emscripten-core / emscripten-core/emscripten
C++ virtual functions crash when called from global constructor
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
Hello, we have a header with public interface that is exported and private implementation located in shared library(built with SIDE_MODULE=1). In constructor of global object we get reference to public interface and try to call virtual function, which leads to crash. We had similar problem before mentioned here: https://github.com/emscripten-core/emscripten/issues/17150
It was fixed, but now similar issue happens when calling virtual functions in constructors of global objects.
**Version of emscripten/emsdk:**
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.14 (4343cbec72b7db283ea3bda1adc6cb1811ae9a73)
clang version 15.0.0 (https://github.com/llvm/llvm-project 7effcbda49ba32991b8955821b8fdbd4f8f303e2)
Target: wasm32-unknown-emscripten
Thread model: posix
```cpp
//Interface.h
#pragma once
#include
class __attribute__((visibility ("default"))) PublicInterface
{
public:
virtual void Foo() = 0;
static PublicInterface& GetInstance();
};
class SomeClass
{
public:
SomeClass() {
std::cout << "SomeClass()" << "\n";
PublicInterface::GetInstance().Foo();
}
};
//Implementation.cpp
#include "Interface.h"
class PrivateImplementation : public PublicInterface
{
public:
void Foo() override {
std::cout << "PrivateImplementation::Foo()" << "\n";
}
};
PublicInterface& PublicInterface::GetInstance() {
std::cout << "PublicInterface::GetInstance()" << "\n";
static PrivateImplementation privateImpl;
return privateImpl;
}
//main.cpp
#include "Interface.h"
SomeClass g_var;
int main() {
return 0;
}
```
**Build commands**
emcc Implementation.cpp -fPIC -fvisibility=hidden -c -o Implementation.o
emcc Implementation.o -sSIDE_MODULE=1 -o dylib1.wasm
emcc main.cpp -fPIC -fvisibility=hidden -c -o main.o
emcc main.o -sMAIN_MODULE=1 -o main.html dylib1.wasm
**Console output**
SomeClass()
PublicInterface::GetInstance()
Uncaught RuntimeError: null function or function signature mismatch
If I reverse runtime callback order in javascript so that global constructors of shared lib run before global constructors of main, problem dissappears, like this
```js
function callRuntimeCallbacks(callbacks) {
callbacks.reverse(); // added this line
while (callbacks.length > 0) {
var callback = callbacks.shift();
if (typeof callback == 'function')
```
Contributor guide
Assessment
This issue has not been assessed yet.