Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package bun-pty for openSUSE:Factory checked in at 2026-09-24 22:56:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/bun-pty (Old) and /work/SRC/openSUSE:Factory/.bun-pty.new.383539 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "bun-pty" Thu Sep 24 22:56:49 2026 rev:2 rq:1380027 version:0.4.10 Changes: -------- --- /work/SRC/openSUSE:Factory/bun-pty/bun-pty.changes 2026-09-16 17:41:56.729054170 +0200 +++ /work/SRC/openSUSE:Factory/.bun-pty.new.383539/bun-pty.changes 2026-09-24 22:59:37.851676215 +0200 @@ -1,0 +2,8 @@ +Wed Sep 23 18:59:59 UTC 2026 - Martin Pluskal <[email protected]> + +- Update to version 0.4.10: + * musl libc support: pre-built musl variants alongside + glibc builds, runtime musl detection +- Refresh the vendored dependencies + +------------------------------------------------------------------- Old: ---- bun-pty-0.4.8.tar.gz New: ---- bun-pty-0.4.10.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ bun-pty.spec ++++++ --- /var/tmp/diff_new_pack.R1Xlcg/_old 2026-09-24 22:59:38.914720667 +0200 +++ /var/tmp/diff_new_pack.R1Xlcg/_new 2026-09-24 22:59:38.916720751 +0200 @@ -17,7 +17,7 @@ Name: bun-pty -Version: 0.4.8 +Version: 0.4.10 Release: 0 Summary: Pseudo-terminal library for Bun FFI consumers License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.R1Xlcg/_old 2026-09-24 22:59:38.947722047 +0200 +++ /var/tmp/diff_new_pack.R1Xlcg/_new 2026-09-24 22:59:38.950722173 +0200 @@ -1,6 +1,6 @@ <services> <service name="cargo_vendor" mode="manual"> - <param name="srctar">bun-pty-0.4.8.tar.gz</param> + <param name="srctar">bun-pty-0.4.10.tar.gz</param> <param name="cargotoml">rust-pty/Cargo.toml</param> <param name="compression">zst</param> </service> ++++++ bun-pty-0.4.8.tar.gz -> bun-pty-0.4.10.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/.github/workflows/publish.yml new/bun-pty-0.4.10/.github/workflows/publish.yml --- old/bun-pty-0.4.8/.github/workflows/publish.yml 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/.github/workflows/publish.yml 2026-06-15 13:17:45.000000000 +0200 @@ -27,6 +27,17 @@ target: aarch64-unknown-linux-gnu zigbuild_target: aarch64-unknown-linux-gnu.2.17 out: librust_pty_arm64.so + # musl builds (Alpine Linux and other musl-based distros) + - runner: ubuntu-22.04 + target: x86_64-unknown-linux-musl + zigbuild_target: x86_64-unknown-linux-musl + out: librust_pty_musl.so + rustflags: -C target-feature=-crt-static + - runner: ubuntu-22.04 + target: aarch64-unknown-linux-musl + zigbuild_target: aarch64-unknown-linux-musl + out: librust_pty_arm64_musl.so + rustflags: -C target-feature=-crt-static - runner: macos-latest target: x86_64-apple-darwin out: librust_pty.dylib @@ -55,6 +66,8 @@ - name: Build rust-pty (Linux with zigbuild) if: matrix.zigbuild_target + env: + RUSTFLAGS: ${{ matrix.rustflags }} run: | cd rust-pty cargo zigbuild --release --target ${{ matrix.zigbuild_target }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/.github/workflows/test.yml new/bun-pty-0.4.10/.github/workflows/test.yml --- old/bun-pty-0.4.8/.github/workflows/test.yml 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/.github/workflows/test.yml 2026-06-15 13:17:45.000000000 +0200 @@ -25,6 +25,7 @@ - runner: windows-latest target: x86_64-pc-windows-gnu + steps: - uses: actions/checkout@v4 @@ -80,3 +81,66 @@ path: coverage/lcov.info if-no-files-found: ignore + build-musl-lib: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: x86_64-unknown-linux-musl + + - uses: Swatinem/rust-cache@v2 + + - name: Install zigbuild + run: | + pip3 install ziglang + cargo install cargo-zigbuild + + - name: Build Rust library (musl with zigbuild) + env: + RUSTFLAGS: -C target-feature=-crt-static + run: cd rust-pty && cargo zigbuild --release --target x86_64-unknown-linux-musl + + - name: Upload musl library + uses: actions/upload-artifact@v4 + with: + name: librust_pty_musl + path: rust-pty/target/x86_64-unknown-linux-musl/release/librust_pty.so + + test-musl: + needs: build-musl-lib + runs-on: ubuntu-latest + container: + image: alpine:3.23 + steps: + - uses: actions/checkout@v4 + + - name: Install system dependencies + run: apk add --no-cache bash curl libgcc libstdc++ + + - name: Download musl library + uses: actions/download-artifact@v4 + with: + name: librust_pty_musl + path: rust-pty/target/release/ + + - name: Rename library to musl variant + run: mv rust-pty/target/release/librust_pty.so rust-pty/target/release/librust_pty_musl.so + + - name: Install Bun + run: | + curl -fsSL https://bun.sh/install | bash + echo "$HOME/.bun/bin" >> $GITHUB_PATH + + - name: Install JS dependencies + run: $HOME/.bun/bin/bun install --ignore-scripts + + - name: Run unit tests + run: $HOME/.bun/bin/bun run test:unit + + - name: Run integration tests + run: $HOME/.bun/bin/bun run test:integration + env: + RUN_INTEGRATION_TESTS: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/CHANGELOG.md new/bun-pty-0.4.10/CHANGELOG.md --- old/bun-pty-0.4.8/CHANGELOG.md 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/CHANGELOG.md 2026-06-15 13:17:45.000000000 +0200 @@ -5,6 +5,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.10] - 2026-06-15 + +### Added +- musl libc support for Alpine Linux and other musl-based distros (#40) + - Ship pre-built musl variants (`librust_pty_musl.so` / `librust_pty_arm64_musl.so`) alongside existing glibc builds via `cargo-zigbuild` with `-C target-feature=-crt-static` + - Detect musl at runtime via `/proc/self/maps` and load the appropriate `.so` + - Add `build-musl-lib` + `test-musl` CI jobs that cross-compile on Ubuntu and run the resulting artifact in `alpine:3.23` + - Fixes #39 + +## [0.4.9] - 2026-06-07 + +### Fixed +- Don't treat transient PTY read/write errors (EINTR/EWOULDBLOCK) as EOF (#42) + - Reader thread now retries transient read errors instead of treating them as EOF. Previously a single `EINTR` (e.g. from a delivered `SIGCHLD` in a signal-heavy host) or `EWOULDBLOCK` ended the reader, which flipped the PTY into an "exited" state — after which `bun_pty_write` silently dropped all input while the child was still alive (a "deaf" PTY) + - Writer thread now retries transient write errors and drops only the current chunk on a fatal error, instead of permanently terminating and dropping all subsequent input + - Fixes #41 + ## [0.4.8] - 2026-01-15 ### Fixed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/flake.lock new/bun-pty-0.4.10/flake.lock --- old/bun-pty-0.4.8/flake.lock 1970-01-01 01:00:00.000000000 +0100 +++ new/bun-pty-0.4.10/flake.lock 2026-06-15 13:17:45.000000000 +0200 @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/flake.nix new/bun-pty-0.4.10/flake.nix --- old/bun-pty-0.4.8/flake.nix 1970-01-01 01:00:00.000000000 +0100 +++ new/bun-pty-0.4.10/flake.nix 2026-06-15 13:17:45.000000000 +0200 @@ -0,0 +1,28 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + cargo + rustc + bun + ]; + }; + } + ); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/package.json new/bun-pty-0.4.10/package.json --- old/bun-pty-0.4.8/package.json 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/package.json 2026-06-15 13:17:45.000000000 +0200 @@ -1,6 +1,6 @@ { "name": "bun-pty", - "version": "0.4.8", + "version": "0.4.10", "description": "Cross-platform pseudoterminal (PTY) implementation for Bun with native performance", "main": "./src/index.ts", "types": "./dist/index.d.ts", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/rust-pty/src/lib.rs new/bun-pty-0.4.10/rust-pty/src/lib.rs --- old/bun-pty-0.4.8/rust-pty/src/lib.rs 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/rust-pty/src/lib.rs 2026-06-15 13:17:45.000000000 +0200 @@ -211,6 +211,17 @@ match rdr.read(&mut buf) { Ok(0) => break, Ok(n) => { let _ = tx.send(Msg::Data(buf[..n].to_vec())); } + // FIX (bun-pty deaf-PTY bug): a transient read error + // (EINTR from a signal, EWOULDBLOCK) must NOT be treated + // as EOF. The old `Err(_) => break` ended the reader on + // any error → Msg::End → exited=true → bun_pty_write + // early-returns CHILD_EXITED forever, permanently deafening + // input while the child is still alive. Retry instead. + Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue, + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { + std::thread::sleep(std::time::Duration::from_millis(2)); + continue; + } Err(_) => break, } } @@ -223,7 +234,24 @@ let mut wtr = master.lock().unwrap().take_writer()?; thread::spawn(move || { while let Ok((data, len)) = rx_w.recv() { - if wtr.write_all(&data[..len]).is_err() { break; } + // Don't let one (possibly transient) write error kill the + // writer thread forever — that would silently drop ALL + // subsequent input. Retry transient errors; on a fatal one, + // drop just this chunk but keep serving later writes. + let mut buf = &data[..len]; + while !buf.is_empty() { + match wtr.write(buf) { + Ok(0) => break, + Ok(n) => buf = &buf[n..], + Err(ref e) + if e.kind() == std::io::ErrorKind::Interrupted + || e.kind() == std::io::ErrorKind::WouldBlock => + { + std::thread::sleep(std::time::Duration::from_millis(2)); + } + Err(_) => break, + } + } let _ = wtr.flush(); } }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/src/terminal.integration.test.ts new/bun-pty-0.4.10/src/terminal.integration.test.ts --- old/bun-pty-0.4.8/src/terminal.integration.test.ts 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/src/terminal.integration.test.ts 2026-06-15 13:17:45.000000000 +0200 @@ -483,4 +483,52 @@ expect(dataReceived).toContain("HelloFromEnv"); }); + + test("Terminal onData listener receives data when set immediately after construction", async () => { + const start = Date.now(); + const maxRuntime = 4000; + let runnings = 1; + while (Date.now() - start < maxRuntime) { + console.log(`[TEST] Iteration ${runnings++}`); + const { success, stdout, stderr } = Bun.spawnSync({ + cmd: ["bun", "test", "terminal.integration.test.ts", "--test-name-pattern", "Terminal sync tests"], + stdout: "pipe", + stderr: "pipe", + env: { ...process.env, SYNC_TESTS: "1" }, + }); + expect(success, `stderr: ${stderr}`).toBe(true); + } + }); + + test.skipIf(!process.env.SYNC_TESTS)("Terminal sync tests", async () => { + let dataReceived = ""; + let hasExited = false; + + const { cmd, args } = echoCommand("sync test"); + console.log("[TEST] Starting terminal with command:", cmd, args); + const terminal = new Terminal(cmd, args); + terminals.push(terminal); + + const exitPromise = new Promise<void>((resolve) => { + terminal.onExit(() => { + console.log("[TEST] Process exited"); + hasExited = true; + resolve(); + }); + }); + const dataPromise = new Promise<void>((resolve) => { + terminal.onData((data) => { + console.log("[TEST] Received data:", data); + dataReceived += data; + if (dataReceived.includes("sync test")) + resolve(); + }); + const timeout = isWindows ? 5000 : 2000; + setTimeout(() => { resolve(); }, timeout); // Timeout to avoid hanging test + }); + + await Promise.race([exitPromise, dataPromise]); + + expect(dataReceived).toContain("sync test"); + }); }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bun-pty-0.4.8/src/terminal.ts new/bun-pty-0.4.10/src/terminal.ts --- old/bun-pty-0.4.8/src/terminal.ts 2026-01-15 20:57:01.000000000 +0100 +++ new/bun-pty-0.4.10/src/terminal.ts 2026-06-15 13:17:45.000000000 +0200 @@ -5,7 +5,7 @@ import { EventEmitter } from "./interfaces"; import type { IPty, IPtyForkOptions, IExitEvent } from "./interfaces"; import { join, dirname, basename } from "node:path"; -import { existsSync } from "node:fs"; +import { existsSync, readFileSync } from "node:fs"; export const DEFAULT_COLS = 80; export const DEFAULT_ROWS = 24; @@ -28,10 +28,21 @@ // terminal.ts – loader fragment only +function isMusl(): boolean { + if (process.platform !== "linux") return false; + try { + return readFileSync("/proc/self/maps", "utf8").includes("ld-musl"); + } catch { + return false; + } +} + function resolveLibPath(): string { const env = process.env.BUN_PTY_LIB; if (env && existsSync(env)) return env; + const musl = isMusl(); + // For bun compile: use statically analyzable require with inline ternary. // Bun evaluates process.platform and process.arch at compile time and only // bundles the file for the target platform. The ternary MUST be inline @@ -40,11 +51,24 @@ try { // @ts-ignore - require returns path for binary files in Bun const embeddedPath = require(`../rust-pty/target/release/${process.platform === "win32" ? "rust_pty.dll" : process.platform === "darwin" ? (process.arch === "arm64" ? "librust_pty_arm64.dylib" : "librust_pty.dylib") : process.arch === "arm64" ? "librust_pty_arm64.so" : "librust_pty.so"}`); - if (embeddedPath) return embeddedPath; + if (embeddedPath && !musl) return embeddedPath; } catch { // Not running as compiled binary, fall through to dynamic resolution } + // For bun compile on Linux musl: embed the musl-specific variant. + // The process.platform guard ensures Bun does not bundle Linux .so files + // into non-Linux compiled binaries. + if (process.platform === "linux") { + try { + // @ts-ignore - require returns path for binary files in Bun + const embeddedMuslPath = require(`../rust-pty/target/release/${process.arch === "arm64" ? "librust_pty_arm64_musl.so" : "librust_pty_musl.so"}`); + if (embeddedMuslPath && musl) return embeddedMuslPath; + } catch { + // Not running as compiled binary, fall through to dynamic resolution + } + } + // Fallback: dynamic resolution for development scenarios const platform = process.platform; const arch = process.arch; @@ -57,6 +81,10 @@ : ["librust_pty.dylib"] : platform === "win32" ? ["rust_pty.dll"] + : musl + ? arch === "arm64" + ? ["librust_pty_arm64_musl.so", "librust_pty_musl.so", "librust_pty_arm64.so", "librust_pty.so"] + : ["librust_pty_musl.so", "librust_pty.so"] : arch === "arm64" ? ["librust_pty_arm64.so", "librust_pty.so"] : ["librust_pty.so"]; @@ -172,7 +200,8 @@ if (this.handle < 0) throw new Error("PTY spawn failed"); this._pid = lib.symbols.bun_pty_get_pid(this.handle); - this._startReadLoop(); + // allow constructor to finish and caller to set up event listeners + queueMicrotask(() => this._startReadLoop()); } /* ------------- accessors ------------- */ ++++++ vendor.tar.zst ++++++ ++++ 150735 lines of diff (skipped)
