Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault introduced v1.1.43 #16277

Closed
Spixmaster opened this issue Jan 9, 2025 · 9 comments · Fixed by #16280
Closed

Segmentation fault introduced v1.1.43 #16277

Spixmaster opened this issue Jan 9, 2025 · 9 comments · Fixed by #16280
Labels
crash An issue that could cause a crash linux An issue that occurs on Linux runtime

Comments

@Spixmaster
Copy link

How can we reproduce the crash?

No response

Relevant log output

============================================================
Bun v1.1.43 (76800b04) Linux x64
Linux Kernel v6.12.8 | glibc v2.40
CPU: sse42 popcnt avx avx2
Args: "bun" "test" "--coverage"
Features: bunfig fetch(13) jsc tsconfig(3) tsconfig_paths
Builtins: "node:buffer" "node:child_process" "node:crypto" "node:http" "node:https" "node:net" "node:perf_hooks" "node:stream" "node:stream/web" "node:string_decoder" "node:url" "node:util" "node:util/types" "node:vm" "node:zlib"
Elapsed: 5223ms | User: 512ms | Sys: 262ms
RSS: 0.88GB | Peak: 0.15GB | Commit: 0.88GB | Faults: 0

panic(main thread): Segmentation fault at address 0x5

Stack Trace (bun.report)

Bun v1.1.43 (76800b0) on linux x86_64 [TestCommand]

Segmentation fault at address 0x00000005

  • ZigGlobalObject.cpp:639: computeErrorInfoWithoutPrepareStackTrace
  • ZigGlobalObject.cpp:714: computeErrorInfoWrapperToString
  • Function.h:53: WTF::Detail::CallableWrapper<WTF::String (...)(...), WTF::String, JSC::VM&, WTF::Vector<JSC::StackFrame, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>&, unsigned int&, unsigned int&, WTF::String&>::call(...)
  • ld-temp.o:0: JSC::ErrorInstance::computeErrorInfo
  • ld-temp.o:0: JSC::Heap::runEndPhase
  • ld-temp.o:0: JSC::Heap::runCurrentPhase
  • ld-temp.o:0: WTF::ScopedLambdaFunctor<void (...), JSC::Heap::collectInMutatorThread()::$_0>::implFunction
  • ld-temp.o:0: JSC::callWithCurrentThreadState

Features: tsconfig_paths, bunfig, fetch, jsc, tsconfig, tsconfig

@Spixmaster Spixmaster added the crash An issue that could cause a crash label Jan 9, 2025
@github-actions github-actions bot added linux An issue that occurs on Linux runtime labels Jan 9, 2025
Copy link
Contributor

github-actions bot commented Jan 9, 2025

Thank you for reporting this crash.

For Bun's internal tracking, this issue is BUN-AWM.

@Jarred-Sumner
Copy link
Collaborator

@Spixmaster i've seen a crash report or two with this - but haven't been able to reproduce.

Can you share a reproduction?

@Spixmaster
Copy link
Author

Spixmaster commented Jan 9, 2025

I will try. Give me a few minutes.

@Jarred-Sumner
Copy link
Collaborator

It's going to be something involving Error objects that are created and then likely never accessed

@Spixmaster
Copy link
Author

Spixmaster commented Jan 9, 2025

This test causes the segmentation fault.

import {assert} from "assert-ts";
import {expect, test} from "bun:test";
import {Window} from "happy-dom";
import {cart} from "../../../src-web/typescript/cart.js";
import {constant} from "../../../src-web/typescript/constant.js";

test("cart.counter.normal", async (): Promise<undefined> =>
{
    //TODO
    console.log("test 4");
    const response: Response = await fetch("http://localhost:5285/"); // This line causes the segmentation fault.
    //TODO
    console.log("test 4.1");
    const window: Window = new Window({url: response.url});
    //@ts-expect-error
    global.window = window;
    //TODO
    console.log("test 4.2");
    //@ts-expect-error
    global.document = window.document;
    //TODO
    console.log("test 4.");
    localStorage.clear();
    //TODO
    console.log("test 4.4");
    document.body.innerHTML = await response.text();

    //TODO
    console.log("test 5");

    const cart_counter: HTMLElement | null = document.getElementById(constant.dom.id.cart_counter);
    assert(cart_counter !== null);

    cart.counter();
    expect(cart_counter.innerText).toStrictEqual("0");

    localStorage.setItem(constant.local_storage.cart.key, "[1, 1]");
    cart.counter();
    expect(cart_counter.innerText).toStrictEqual("2");
    //TODO
    console.log("test 6");
});

Output:

✓ cart.add.normal [76.44ms]
test 4
============================================================
Bun v1.1.43 (76800b04) Linux x64
Linux Kernel v6.12.8 | glibc v2.40
CPU: sse42 popcnt avx avx2
Args: "bun" "test" "--coverage"
Features: bunfig fetch(9) jsc transpiler_cache(4) tsconfig(3) tsconfig_paths
Builtins: "node:buffer" "node:child_process" "node:crypto" "node:http" "node:https" "node:net" "node:perf_hooks" "node:stream" "node:stream/web" "node:string_decoder" "node:url" "node:util" "node:util/types" "node:vm" "node:zlib"
Elapsed: 1113ms | User: 467ms | Sys: 87ms
RSS: 0.91GB | Peak: 132.93MB | Commit: 0.91GB | Faults: 0

panic(main thread): Segmentation fault at address 0x5

As background information, I run a C++ HTTP server on port 5285. I cannot give you the binary.

I tried to reproduce with another fetch() to a different website but it did not cause a segmentation fault. I will continue to try but maybe this already helps you. I will reach out again as soon as I have something reproducible.

@Spixmaster
Copy link
Author

Some further testing.

For whatever reason, this test passes although variable response_2 is assigned the result of the same function which causes a segmentation fault in a different place.

test("reproduction", async (): Promise<undefined> =>
{
    //TODO
    console.log("test 0.0");
    const response: Response = await fetch("http://example.com/");
    const response_1: Response = await fetch("https://example.com/");
    //TODO
    console.log("test 0.1");
    const response_2: Response = await fetch("http://localhost:5285/");
    //TODO
    console.log("test 0.2");
});

The error is not consistent. In a different execution, this happened.

import {assert} from "assert-ts";
import {expect, test} from "bun:test";
import {Window} from "happy-dom";
import {cart} from "../../../src-web/typescript/cart.js";
import {constant} from "../../../src-web/typescript/constant.js";

test("cart.counter.normal", async (): Promise<undefined> =>
{
    //TODO
    console.log("test 4");
    const response: Response = await fetch("http://localhost:5285/");
    //TODO
    console.log("test 4.1");
    const window: Window = new Window({url: response.url}); // Error may be here.
    //@ts-expect-error
    global.window = window; // Error may be here.
    //TODO
    console.log("test 4.2");
    //@ts-expect-error
    global.document = window.document;
    //TODO
    console.log("test 4.");
    localStorage.clear();
    //TODO
    console.log("test 4.4");
    document.body.innerHTML = await response.text();

    //TODO
    console.log("test 5");

    const cart_counter: HTMLElement | null = document.getElementById(constant.dom.id.cart_counter);
    assert(cart_counter !== null);

    cart.counter();
    expect(cart_counter.innerText).toStrictEqual("0");

    localStorage.setItem(constant.local_storage.cart.key, "[1, 1]");
    cart.counter();
    expect(cart_counter.innerText).toStrictEqual("2");
    //TODO
    console.log("test 6");
});
❯ bun test --coverage
bun test v1.1.43 (76800b04)

tests/src-web/typescript/cart.test.ts:
test 0.0
test 0.1
test 0.2
✓ reproduction [982.99ms]
test 1
test 2
test 3
✓ cart.add.normal [135.38ms]
test 4
test 4.1
============================================================
Bun v1.1.43 (76800b04) Linux x64
Linux Kernel v6.12.8 | glibc v2.40
CPU: sse42 popcnt avx avx2
Args: "bun" "test" "--coverage"
Features: bunfig fetch(10) jsc transpiler_cache(4) tsconfig(3) tsconfig_paths
Builtins: "node:buffer" "node:child_process" "node:crypto" "node:http" "node:https" "node:net" "node:perf_hooks" "node:stream" "node:stream/web" "node:string_decoder" "node:url" "node:util" "node:util/types" "node:vm" "node:zlib"
Elapsed: 1560ms | User: 499ms | Sys: 115ms
RSS: 0.79GB | Peak: 130.63MB | Commit: 0.79GB | Faults: 0

panic(main thread): Segmentation fault at address 0x5

@Jarred-Sumner
Copy link
Collaborator

Still not able to repro yet, here's what I tried:

import { assert } from "assert-ts";
import { expect, test } from "bun:test";
import { Window } from "happy-dom";
const server = Bun.serve({
  port: 5285,
  fetch(req) {
    return new Response("Hello World");
  },
});
const cart = {
  counter: () => {
    console.log("counter");
  },
};

test("reproduction", async (): Promise<undefined> => {
  //TODO
  console.log("test 0.0");
  Bun.gc(true);
  const response: Response = await fetch("http://example.com/");
  const response_1: Response = await fetch("https://example.com/");
  //TODO
  Bun.gc(true);
  console.log("test 0.1");
  const response_2: Response = await fetch("http://localhost:5285/");
  //TODO
  console.log("test 0.2");
  Bun.gc(true);
});

test("cart.counter.normal", async (): Promise<undefined> => {
  //TODO
  console.log("test 4");
  Bun.gc(true);
  const response: Response = await fetch("http://localhost:5285/");
  //TODO
  console.log("test 4.1");
  const window: Window = new Window({ url: response.url }); // Error may be here.
  const localStorage = window.localStorage;
  //@ts-expect-error
  global.window = window; // Error may be here.
  //TODO
  console.log("test 4.2");
  Bun.gc(true);
  //@ts-expect-error
  global.document = window.document;
  //TODO
  console.log("test 4.");
  Bun.gc(true);
  localStorage.clear();
  //TODO
  console.log("test 4.4");
  document.body.innerHTML = await response.text();
  Bun.gc(true);
  //TODO
  console.log("test 5");

  const cart_counter: HTMLElement | null =
    document.getElementById("cart_counter");
  assert(cart_counter !== null);

  cart.counter();
  expect(cart_counter.innerText).toStrictEqual("0");

  localStorage.setItem("key", "[1, 1]");
  Bun.gc(true);
  cart.counter();
  expect(cart_counter.innerText).toStrictEqual("2");
  Bun.gc(true);
  //TODO
  console.log("test 6");
  Bun.gc(true);
});

I also tried adding happy-dom via --preload

I think it depends on those other files to happen

@Spixmaster
Copy link
Author

Spixmaster commented Jan 9, 2025

@Jarred-Sumner I am able to reproduce!

Source code:

import {assert} from "assert-ts";
import {expect, test} from "bun:test";
import {Window} from "happy-dom";
import {cart} from "../../../src-web/typescript/cart.js";
import {constant} from "../../../src-web/typescript/constant.js";

test("reproduction", async (): Promise<undefined> =>
{
    //TODO
    console.log("start");

    for(let i: number = 0; i < 10; ++i)
    {
        const response: Response = await fetch("https://youtube.com/");
        const window: Window = new Window({url: response.url});
        //@ts-expect-error
        global.window = window;
        //@ts-expect-error
        global.document = window.document;
        localStorage.clear();
        document.body.innerHTML = await response.text();
    }

    //TODO
    console.log("test a");

    for(let i: number = 0; i < 10; ++i)
    {
        const response: Response = await fetch("https://facebook.com/");
        const window: Window = new Window({url: response.url});
        //@ts-expect-error
        global.window = window;
        //@ts-expect-error
        global.document = window.document;
        localStorage.clear();
        document.body.innerHTML = await response.text();
    }

    //TODO
    console.log("test b");

    for(let i: number = 0; i < 10; ++i)
    {
        const response: Response = await fetch("https://reddit.com/");
        const window: Window = new Window({url: response.url});
        //@ts-expect-error
        global.window = window;
        //@ts-expect-error
        global.document = window.document;
        localStorage.clear();
        document.body.innerHTML = await response.text();
    }

    //TODO
    console.log("end");
});

Output (The warnings can be ignored.):

❯ bun test --coverage
bun test v1.1.43 (76800b04)

tests/src-web/typescript/cart.test.ts:
start
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
31 |         "moduleSuffixes": [""],
                               ^
warn: moduleSuffixes is not supported yet
   at /home/matheus/programmieren/c++/argo/tsconfig.json:31:27
============================================================
Bun v1.1.43 (76800b04) Linux x64
Linux Kernel v6.12.8 | glibc v2.40
CPU: sse42 popcnt avx avx2
Args: "bun" "test" "--coverage"
Features: Bun.stderr bunfig fetch(10) jsc spawn(10) transpiler_cache(4) tsconfig(3) tsconfig_paths
Builtins: "node:buffer" "node:child_process" "node:crypto" "node:http" "node:https" "node:net" "node:perf_hooks" "node:stream" "node:stream/web" "node:string_decoder" "node:url" "node:util" "node:util/types" "node:vm" "node:zlib"
Elapsed: 2867ms | User: 1104ms | Sys: 301ms
RSS: 0.76GB | Peak: 0.23GB | Commit: 0.76GB | Faults: 0

panic(main thread): Segmentation fault at address 0x5

bunfig.toml:

preload = "./preload.ts"

preload.ts:

import {GlobalRegistrator} from "@happy-dom/global-registrator";

const original_fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>,
    (input: globalThis.Request | string | URL, init?: RequestInit): Promise<Response>
} = global.fetch;

GlobalRegistrator.register();

global.fetch = original_fetch;

@Jarred-Sumner
Copy link
Collaborator

okay very interesting I wonder why we're adding that warning multiple times

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crash An issue that could cause a crash linux An issue that occurs on Linux runtime
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants