mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-10-09 04:42:30 -04:00
ReleaseFast faults otherwise leave only an exit status. Record the signal, original fault registers and build identity without entering panic reporting, the IO backend, an allocator-backed unwinder or telemetry. For pipe stderr, prepare an independent nonblocking procfs descriptor before threads start; never change the inherited descriptor's shared flags. For sockets, use per-call nonblocking send flags. Drop output for unsupported sinks or backpressure, then re-raise the original signal. Other platforms retain their existing signal handling. Core limits still apply, but cores capture the re-raise context rather than the original fault; document that distinction. Subprocess tests cover full pipes and sockets with undrained readers, unavailable/read-only/file stderr, unchanged flags, repeated attachment, held panic locks and hardware faults.
84 lines
3.2 KiB
Zig
84 lines
3.2 KiB
Zig
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
|
//
|
|
// Francis Bouvier <francis@lightpanda.io>
|
|
// Pierre Tachoire <pierre@lightpanda.io>
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
//! Opt-in core-dump suppression.
|
|
//!
|
|
//! On Linux, fatal signals are re-raised after nonblocking diagnostics.
|
|
//! Core limits still apply, but the core captures the re-raise context;
|
|
//! the diagnostic record holds the original fault PC. Other platforms keep
|
|
//! their existing signal handling. Signals and panics can produce cores. When many
|
|
//! instances run under a shared `core_pattern` crash reporter — e.g. a
|
|
//! containerized crawl fleet — those dumps become pure storage and alert
|
|
//! noise, and a browser core can capture the contents of arbitrary pages.
|
|
//! `LIGHTPANDA_DISABLE_CORE_DUMP` lets an operator drop the cores while
|
|
//! leaving the default behavior (and local debugging) untouched.
|
|
|
|
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
const lp = @import("lightpanda.zig");
|
|
|
|
const log = lp.log;
|
|
|
|
pub fn disableIfRequested() void {
|
|
if (!shouldDisable()) return;
|
|
disable() catch |err| {
|
|
log.warn(.app, "could not disable core dumps", .{ .err = err });
|
|
};
|
|
}
|
|
|
|
fn shouldDisable() bool {
|
|
if (builtin.os.tag == .windows) return false;
|
|
return std.c.getenv("LIGHTPANDA_DISABLE_CORE_DUMP") != null;
|
|
}
|
|
|
|
// Zeroes only the soft limit; that is what the kernel consults when deciding
|
|
// whether to dump (including the piped-`core_pattern` opt-out), and keeping the
|
|
// hard limit lets the process raise it again if it ever needs to.
|
|
fn disable() !void {
|
|
var limit = try std.posix.getrlimit(.CORE);
|
|
limit.cur = 0;
|
|
try std.posix.setrlimit(.CORE, limit);
|
|
}
|
|
|
|
const testing = @import("testing.zig");
|
|
|
|
extern fn setenv(name: [*:0]u8, value: [*:0]u8, override: c_int) c_int;
|
|
extern fn unsetenv(name: [*:0]u8) c_int;
|
|
|
|
test "core_dump: disabled only when the env var is set" {
|
|
_ = unsetenv(@constCast("LIGHTPANDA_DISABLE_CORE_DUMP"));
|
|
try testing.expectEqual(false, shouldDisable());
|
|
|
|
_ = setenv(@constCast("LIGHTPANDA_DISABLE_CORE_DUMP"), @constCast(""), 1);
|
|
defer _ = unsetenv(@constCast("LIGHTPANDA_DISABLE_CORE_DUMP"));
|
|
try testing.expectEqual(true, shouldDisable());
|
|
}
|
|
|
|
test "core_dump: disable zeroes the soft RLIMIT_CORE" {
|
|
if (builtin.os.tag == .windows) return;
|
|
|
|
const original = try std.posix.getrlimit(.CORE);
|
|
defer std.posix.setrlimit(.CORE, original) catch {};
|
|
|
|
try disable();
|
|
|
|
const after = try std.posix.getrlimit(.CORE);
|
|
try testing.expectEqual(@as(@TypeOf(after.cur), 0), after.cur);
|
|
try testing.expectEqual(original.max, after.max);
|
|
}
|