From dbae325cdb9ca09f5f236eab62df6c2806e77fe6 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 4 Oct 2026 13:34:35 +0300 Subject: [PATCH] add stack size limit --- build.zig | 21 ++++++++++++++++++++- src/app.zig | 4 ++-- src/platform/root.zig | 15 ++++++++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index e7f8689..0fb5fc2 100644 --- a/build.zig +++ b/build.zig @@ -128,7 +128,11 @@ fn getPackageSuffix(target: Build.ResolvedTarget) []const u8 { }; } +const bytes_per_kib = 1024; +const bytes_per_mib = bytes_per_kib * 1024; + const ProjectOptions = struct { + stack_size: usize = 4 * bytes_per_mib, imgui: ?bool = null, assets_from_filesystem: ?bool = null, tracy: ?bool = null, @@ -188,6 +192,9 @@ fn buildProject(ctx: Context, target: Build.ResolvedTarget, optimize: std.builti if (assets_from_filesystem) { build_options.addOptionPathDirectory("assets_dir", assets_dir); } + if (is_debug and !is_wasm) { + build_options.addOption(usize, "stack_size_limit", opts.stack_size); + } platform_mod.addOptions("build_options", build_options); platform_mod.addImport("embedded_assets", try createAssetsModule(b, assets_dir, &asset_files)); @@ -275,6 +282,18 @@ fn buildProject(ctx: Context, target: Build.ResolvedTarget, optimize: std.builti &(dep_sokol.artifact("sokol_clib").step) ); + var extra_args: std.ArrayList([]const u8) = .empty; + try extra_args.append(b.allocator, "-sALLOW_MEMORY_GROWTH"); + try extra_args.append(b.allocator, "-sENVIRONMENT=web"); + try extra_args.append(b.allocator, b.fmt("-sSTACK_SIZE={}", .{opts.stack_size})); + + if (is_debug) { + try extra_args.append(b.allocator, "-sASSERTIONS=2"); + try extra_args.append(b.allocator, "-sSTACK_OVERFLOW_CHECK=2"); + try extra_args.append(b.allocator, "-gsource-map"); + try extra_args.append(b.allocator, "-g2"); + } + const link_step = try sokol.emLinkStep(b, .{ .lib_main = main_lib, .target = target, @@ -284,7 +303,7 @@ fn buildProject(ctx: Context, target: Build.ResolvedTarget, optimize: std.builti .use_emmalloc = true, .use_filesystem = true, .shell_file_path = b.path("src/platform/shell.html"), - .extra_args = &.{ "-sALLOW_MEMORY_GROWTH", "-sENVIRONMENT=web" } + .extra_args = extra_args.items }); return ProjectResult{ diff --git a/src/app.zig b/src/app.zig index 8a06889..2ae0669 100644 --- a/src/app.zig +++ b/src/app.zig @@ -356,7 +356,7 @@ footstep_sound: Audio.SoundId = .nil, sfx_bus: Audio.BusId, game_scene: GameScene, -in_main_menu: bool = false, +in_main_menu: bool = true, main_menu_state: UI.State = .empty, pub fn init(self: *App, plt: Platform.Init) !?u8 { @@ -523,7 +523,7 @@ fn loadLevels(self: *App, gpa: Allocator, assets: *Platform.Assets) !std.ArrayLi } }; - std.mem.sort(World, levels.items, Context{}, Context.lessThan); + std.sort.insertion(World, levels.items, Context{}, Context.lessThan); return levels; } diff --git a/src/platform/root.zig b/src/platform/root.zig index 851ba83..a8af323 100644 --- a/src/platform/root.zig +++ b/src/platform/root.zig @@ -623,7 +623,7 @@ pub const Frame = struct { } }; -pub fn run(App: type, opts: RunOptions) void { +fn runThread(App: type, opts: RunOptions) void { const gpa = opts.init.gpa; const io = opts.init.io; @@ -706,6 +706,19 @@ pub fn run(App: type, opts: RunOptions) void { }); } +pub fn run(App: type, opts: RunOptions) void { + if (@hasDecl(build_options, "stack_size_limit")) { + var t = std.Thread.spawn( + .{ .stack_size = build_options.stack_size_limit }, + runThread, + .{App, opts} + ) catch @panic("Failed to launch thread for limiting stack size"); + t.join(); + } else { + runThread(App, opts); + } +} + fn posixSignalHandler(sig: std.posix.SIG) callconv(.c) void { _ = sig; sapp.requestQuit();