Skip to content

[BUG] Segfault on combo of global ctors, ostream, wasi #33175

Description

@tqchen

This is an issue for node's WASI integration with emscripten.

both global ctors need to be called, and ostream being used in the WASM standalone mode (emsdk latest upstream).

I have a case where I need to call the global static initializers(need to call _start before running other functions), but also have ostream in the code.

What was happening is that when ostream is being used in the code and it somehow triggers certain things to be added to global ctors, and then calling global ctors resulted in a segfault. So far I only get this error on node14, and I am not sure if it is related to the use of WASI.

C++

#include <emscripten.h>
#include <vector>
#include <sstream>

// static intializer, need to call _start
static std::vector<int> x = {1, 2, 3};

extern "C" {
EMSCRIPTEN_KEEPALIVE
int GetX(int i) {
   // use of ostream somehow makes _start fail.
    std::ostringstream os;
    os << "x";
    return x[i];
}
}
wasm_test.wasm: wasm_test.cc
	@mkdir -p $(@D)
	emcc -O3 -std=c++11 -o $@ $<

NodeJS

const { WASI } = require('wasi');

const wasi = new WASI({
    args: process.argv,
    env: process.env
  });

const binary = require('fs').readFileSync('build/wasm_test.wasm');

WebAssembly.instantiate(binary,
    { env: {}, wasi_snapshot_preview1: wasi.wasiImport }).then(({ instance }) => {
  // trigger ctors
  instance.exports._start();
  // test the static vars are correctly initialized.
  console.log(instance.exports.GetX(0));
});
node --experimental-wasi-unstable-preview1  --experimental-wasm-bigint test_wasm.js 

Relevant issue in the emscripten emscripten-core/emscripten#11001

Activity

  1. changed the title [-]Segfault on combo of global ctors, ostream, wasi[/-] [+][BUG] Segfault on combo of global ctors, ostream, wasi[/+] on Apr 30, 2020
  2. tqchen commented on Apr 30, 2020

    @tqchen
    Author

    Backtrace, note that the same code works for other wasi runtime.

    Thread 1 "node" received signal SIGSEGV, Segmentation fault.
    0x0000000001060788 in v8::internal::Runtime::GetObjectProperty(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, bool*) ()
    (gdb) bt
    #0  0x0000000001060788 in v8::internal::Runtime::GetObjectProperty(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, bool*) ()
    #1  0x0000000000ba7b67 in v8::Object::Get(v8::Local<v8::Context>, v8::Local<v8::Value>) ()
    #2  0x0000000000ad0f10 in node::wasi::WASI::backingStore(char**, unsigned long*) ()
    #3  0x0000000000ad1b71 in node::wasi::WASI::EnvironSizesGet(v8::FunctionCallbackInfo<v8::Value> const&) ()
    #4  0x0000000000c02b0b in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) ()
    #5  0x0000000000c040b6 in v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) ()
    #6  0x0000000000c04736 in v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) ()
    #7  0x00000000013a6339 in Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit ()
    #8  0x0000137ee359220a in ?? ()
    
  3. added
    confirmed-bugIssues and PRs for confirmed bugs.
    wasiIssues and PRs related to the WebAssembly System Interface.
    c++Issues and PRs that require attention from people who are familiar with C++.
    good first issueIssues that are suitable for first-time contributors.
    on Apr 30, 2020
  4. addaleax commented on Apr 30, 2020

    @addaleax
    Member

    Using wasi.start(instance); instead of instance.exports._start(); fixes this, but I agree that this shouldn’t crash. Essentially, https://github.com/nodejs/node/blob/master/src/node_wasi.cc#L1794-L1798 is missing another check that verifies that memory is not empty (i.e. that _setMemory() has been called at some point).

    I’ve attached
    the generated WASM here so that if somebody wants to pick this up, they don’t have to install emscripten to reproduce this.

  5. removed
    good first issueIssues that are suitable for first-time contributors.
    on May 1, 2020
  6. gengjiawen commented on Sep 29, 2020

    @gengjiawen
    Member

    Should be fixed by #33184. Please reopen if this persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++Issues and PRs that require attention from people who are familiar with C++.confirmed-bugIssues and PRs for confirmed bugs.wasiIssues and PRs related to the WebAssembly System Interface.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions