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

panic(main thread): Segmentation fault at address 0x0 oh no: Bun has crashed. #13482

Closed
burgil opened this issue Aug 23, 2024 · 0 comments
Closed
Labels
crash An issue that could cause a crash runtime windows An issue that is known to occur on Windows

Comments

@burgil
Copy link

burgil commented Aug 23, 2024

How can we reproduce the crash?

Sorry I do not have a minimal reproduction, feel free to close this if it's not helping to fix any issues.

C:\Windows\system32>bun --version
1.1.25

Related tags for context: Win10, VSCode Insiders, Bun, Vite, Python

The issue:

I run bun start, everything works great (and fast xD) almost always, randomly after a random amount of time, usually a very long time, the server closes itself like every now and then with a similar error, I noticed it is happening even when I am off the keyboard and at completely random occasions.

It might be worth mentioning that this issue is hunting me from version v1.1.22 to v1.1.25, and possibly even two versions before that, on two different projects, one of them is only vite and tauri, and the other is this one I am describing below, but it could be anything else, I just upgraded from v1.1.23 to v1.1.24 and then later to v1.1.25 on this project and I noticed that still very randomly things will crash on any version I tried so far, I have my task manager running in another screen at all times always and I don't feel like it's happening due to resource consumption, I have 16GB ram, 4 cores i7 3.5ghz, desktop, 3 monitors, 8gb amd gpu

(Text logs are below)

image

Possible reproduction steps:

when I run bun start I made it run:
$ bun utils/warning.js --bun && poetry run start

Yeah I know I call python here but my project is a vite app hooked up with a python templating bundler I've made, when it's running it has two different web servers on two different ports, so it's a pretty intense application compared to an empty project, I use vite as a middleware and poetry launches bun too after launching a custom python watcher, so a lot of moving parts in play here. (A lot more info & details below)

(Error logs should be all the way down here after the code examples)
I do not have any other error logs coming from other scripts or any indication as to what is causing this issue

Although the project is technically big, the resource consumption is stable, the website loads in under 50ms, and everything works smooth and fast almost always, it is almost as if bun runs out of assigned memory and then crashes almost randomly, or something is that possible? could be when my PC resource consumption spikes maybe, although only a theory, it doesn't feel like this is happening due to memory spikes, it is happening even when the computer is at a stable state with minimum applications and things running. I even tried to add into the exclusion bun and bun folder figured that might help but the issue kept randomly happening.

image

image

If the stuff in the poetry become relevant at any point, this is the start script:
image

and inside a folder I called utils/ I added a launcher.py with something like:

import os
import time
import subprocess
import threading
import sys
import socket
from typing import Optional, List
import psutil

parent_dir: str = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
os.chdir(parent_dir)

def start_process(command: List[str]) -> subprocess.Popen[bytes]:
    return subprocess.Popen(command, preexec_fn=os.setsid if sys.platform != 'win32' else None)

def kill_process_tree(pid: int) -> None:
    try:
        parent: psutil.Process = psutil.Process(pid)
        for child in parent.children(recursive=True):
            child.kill()
        parent.kill()
    except psutil.NoSuchProcess:
        pass

def stop_process(process: Optional[subprocess.Popen[bytes]]) -> None:
    if process and process.poll() is None:
        kill_process_tree(process.pid)

def monitor_processes(bun_process: subprocess.Popen[bytes], harbor_process: subprocess.Popen[bytes]) -> None:
    bun_process.wait()
    stop_process(harbor_process)

def wait_for_port(port: int, host: str = 'localhost', timeout: int = 30) -> bool:
    start_time = time.time()
    while time.time() - start_time < timeout:
        try:
            with socket.create_connection((host, port), timeout=2):
                return True
        except (ConnectionRefusedError, OSError):
            time.sleep(0.5)
    return False

def find_process_using_port(port: int) -> Optional[psutil.Process]:
    for conn in psutil.net_connections(kind='inet'):
        if conn.laddr and conn.laddr.port == port and conn.status == psutil.CONN_LISTEN:
            try:
                return psutil.Process(conn.pid)
            except psutil.NoSuchProcess:
                return None
    return None

def ensure_ports_closed(ports: List[int]) -> None:
    for port in ports:
        process = find_process_using_port(port)
        while process and process.is_running():
            try:
                process.wait(timeout=10)
            except psutil.TimeoutExpired:
                print(f"Process on port {port} did not close in time. Attempting to terminate gracefully...")
                process.terminate()
                try:
                    process.wait(timeout=5)
                except psutil.TimeoutExpired:
                    print(f"Process on port {port} did not terminate, attempting to kill...")
                    process.kill()
                    process.wait(timeout=3)
                    print(f"Process on port {port} forcefully killed.")
            process = find_process_using_port(port)

def main() -> None:
    harbor_process: Optional[subprocess.Popen[bytes]] = None
    bun_process: Optional[subprocess.Popen[bytes]] = None
    monitor_thread: Optional[threading.Thread] = None
    try:
        ensure_ports_closed([5000, 5173])
        harbor_process = start_process(["poetry", "run", "harbor"])
        if not wait_for_port(5000):
            print("Failed to detect service on port 5000. Exiting...")
            return
        bun_process = start_process(["bun", "run", "web"])
        print("running.")
        monitor_thread = threading.Thread(target=monitor_processes, args=(bun_process, harbor_process))
        monitor_thread.start()
        monitor_thread.join()
    except KeyboardInterrupt:
        pass
    finally:
        stop_process(harbor_process)
        stop_process(bun_process)
        if monitor_thread and monitor_thread.is_alive():
            monitor_thread.join()
        ensure_ports_closed([5000, 5173])
        sys.stdout = open(os.devnull, 'w')

if __name__ == "__main__":
    main()

As for the launcher script, it basically calls in two different threads that watch for when they close, in order to close the parent process.
So it runs:

  • bun run web
  • poetry run harbor

So basically bun run web runs bun utils/warning.js --package && bun server.mts where a basic middleware vite example is located

the warning.js util simply checks if there is package-lock.json and terminates if it is found with a warning.

And poetry run harbor runs a separate python watchdog script that watches the file directory for changes and then builds an index.html file when others are changed.

This all works fine with no issues except this very random very rare yet repeating issue, that I hoped to share insights about to the great bun team.

I know, a lot of things calling each other in start up, but we are also trying to push innovation xD.

here is the relevant part of my package.json:

{
	"name": "vite-project",
	"private": true,
	"version": "0.0.0",
	"type": "module",
	"scripts": {
		"start": "bun utils/warning.js --bun && poetry run start",
		"web": "bun utils/warning.js --package && bun server.mts",
		"dev": "vite",
		...

here is server.mts for the custom vite middleware server:

import express, { type Request, type Response, type NextFunction } from 'express';
import { createServer as createViteServer } from 'vite';
import path from 'node:path';

async function createServer() {
  const app = express();
  const vite = await createViteServer({
    server: {
      middlewareMode: true,
    },
  });
  app.use(vite.middlewares);
  app.use('*', async (req: Request, res: Response, next: NextFunction) => {
    try {
      const url = req.originalUrl;
      const template = await vite.transformIndexHtml(url, path.resolve(__dirname, 'index.html'));
      res.status(200).set({ 'Content-Type': 'text/html' }).end(template);
    } catch (e) {
      vite.ssrFixStacktrace(e);
      next(e);
    }
  });

  app.listen(5173, () => {
    console.log('Your frontend is live and running smoothly at: http://localhost:5173');
  });
}

createServer();

and for the final moving part, I think, is this part inside my vite.config.mts file:

export default defineConfig({
	clearScreen: false,
	server: {
		middlewareMode: true,
		hmr: {
			port: 24678,
		},
	},
	...

sample pyproject.toml:

[tool.poetry]
authors = ["Your Name"]
description = "A project built with My-Bundler."
license = "MIT"
name = "my-project"
packages = [
  {include = "*", from = "utils"},
]
readme = "README.md"
version = "0.1.0"
include = [
  "README.md",
  "LICENSE",
]

[tool.poetry.dependencies]
fastapi = "^0.112.1"
loguru = "^0.7.2"
python = "^3.12"
rich = "^13.7.1"
toml = "^0.10.2"
typer = "^0.12.4"
uvicorn = "^0.30.6"
watchdog = "^4.0.2"
watchfiles = "^0.23.0"
cryptography = "^43.0.0"
jinja2 = "^3.1.4"
wsproto = "^1.2.0"
psutil = "^6.0.0"

[tool.poetry.dependencies.uvloop]
markers = "sys_platform == 'linux'"
version = "^0.20.0"

[tool.poetry.scripts]
start = "utils.launcher:main"
watcher = "utils.watcher:main"
build = "index:main"
harbor = "harbor.harbor:run_server"

[build-system]
build-backend = "poetry.core.masonry.api"
requires = ["poetry-core"]

Relevant log output

============================================================
Windows v.win10_fe
CPU: sse42 avx avx2
Args: "C:\Users\Burgil\.bun\bin\bun.exe" "server.mts"
Features: jsc Bun.stdin http_server(2) spawn(2) transpiler_cache(28) tsconfig(10)
Builtins: "bun:jsc" "bun:main" "node:assert" "node:async_hooks" "node:buffer" "node:child_process" "node:crypto" "node:dns" "node:events" "node:fs" "node:fs/promises" "node:http" "node:https" "node:module" "node:net" "node:os" "node:path" "node:perf_hooks" "node:querystring" "node:readline" "node:stream" "node:string_decoder" "node:tls" "node:tty" "node:url" "node:util" "node:util/types" "node:zlib" "node:worker_threads" "ws" "node:v8"
Elapsed: 4397084ms | User: 34343ms | Sys: 6203ms
RSS: 0.40GB | Peak: 0.75GB | Commit: 5.22GB | Faults: 496294

panic(main thread): Segmentation fault at address 0x0
oh no: Bun has crashed. This indicates a bug in Bun, not your code.

To send a redacted crash report to Bun's team,
please file a GitHub issue using the link below:

 https://bun.report/1.1.25/wa21bac094Aqggh0CA2AA

error: script "web" exited with code 3

Stack Trace (bun.report)

Bun v1.1.25-canary (1bac094) on windows x86_64 [AutoCommand]

Segmentation fault at address 0x00000000

Features: jsc, Bun.stdin, http_server, spawn, transpiler_cache, tsconfig

@burgil burgil added the crash An issue that could cause a crash label Aug 23, 2024
@github-actions github-actions bot added runtime windows An issue that is known to occur on Windows labels Aug 23, 2024
@burgil burgil closed this as completed Aug 24, 2024
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 runtime windows An issue that is known to occur on Windows
Projects
None yet
Development

No branches or pull requests

1 participant