@@ -30,6 +30,9 @@ const Browser = @import("browser/browser.zig").Browser;
3030const build_config = @import ("build_config" );
3131const parser = @import ("browser/netsurf.zig" );
3232
33+ var _app : ? * App = null ;
34+ var _server : ? Server = null ;
35+
3336pub fn main () ! void {
3437 // allocator
3538 // - in Debug mode we use the General Purpose Allocator to detect memory leaks
@@ -41,29 +44,42 @@ pub fn main() !void {
4144 if (gpa .detectLeaks ()) std .posix .exit (1 );
4245 };
4346
44- // Exit the program on SIGINT signal. When running the browser in a Docker
45- // container, sending a CTRL-C (SIGINT) signal is catched but doesn't exit
46- // the program. Here we force exiting on SIGINT.
47- std .posix .sigaction (std .posix .SIG .INT , & std.posix.Sigaction {
47+ run (alloc ) catch | err | {
48+ // If explicit filters were set, they won't be valid anymore because
49+ // the args_arena is gone. We need to set it to something that's not
50+ // invalid. (We should just move the args_arena up to main)
51+ log .opts .filter_scopes = &.{};
52+ log .fatal (.app , "exit" , .{ .err = err });
53+ std .posix .exit (1 );
54+ };
55+ }
56+
57+ // Handle app shutdown gracefuly on signals.
58+ fn shutdown () void {
59+ const sigaction : std.posix.Sigaction = .{
4860 .handler = .{
4961 .handler = struct {
5062 pub fn handler (_ : c_int ) callconv (.c ) void {
63+ // Shutdown service gracefuly.
64+ if (_server ) | server | {
65+ server .deinit ();
66+ }
67+ if (_app ) | app | {
68+ app .deinit ();
69+ }
5170 std .posix .exit (0 );
5271 }
5372 }.handler ,
5473 },
5574 .mask = std .posix .empty_sigset ,
5675 .flags = 0 ,
57- }, null );
58-
59- run (alloc ) catch | err | {
60- // If explicit filters were set, they won't be valid anymore because
61- // the args_arena is gone. We need to set it to something that's not
62- // invalid. (We should just move the args_arena up to main)
63- log .opts .filter_scopes = &.{};
64- log .fatal (.app , "exit" , .{ .err = err });
65- std .posix .exit (1 );
6676 };
77+ // Exit the program on SIGINT signal. When running the browser in a Docker
78+ // container, sending a CTRL-C (SIGINT) signal is catched but doesn't exit
79+ // the program. Here we force exiting on SIGINT.
80+ std .posix .sigaction (std .posix .SIG .INT , & sigaction , null );
81+ std .posix .sigaction (std .posix .SIG .TERM , & sigaction , null );
82+ std .posix .sigaction (std .posix .SIG .QUIT , & sigaction , null );
6783}
6884
6985fn run (alloc : Allocator ) ! void {
@@ -96,7 +112,8 @@ fn run(alloc: Allocator) !void {
96112 const platform = try Platform .init ();
97113 defer platform .deinit ();
98114
99- var app = try App .init (alloc , .{
115+ // _app is global to handle graceful shutdown.
116+ _app = try App .init (alloc , .{
100117 .run_mode = args .mode ,
101118 .platform = & platform ,
102119 .http_proxy = args .httpProxy (),
@@ -107,6 +124,7 @@ fn run(alloc: Allocator) !void {
107124 .http_max_host_open = args .httpMaxHostOpen (),
108125 .http_max_concurrent = args .httpMaxConcurrent (),
109126 });
127+ const app = _app .? ;
110128 defer app .deinit ();
111129 app .telemetry .record (.{ .run = {} });
112130
@@ -118,7 +136,9 @@ fn run(alloc: Allocator) !void {
118136 return args .printUsageAndExit (false );
119137 };
120138
121- var server = try Server .init (app , address );
139+ // _server is global to handle graceful shutdown.
140+ _server = try Server .init (app , address );
141+ const server = & _server .? ;
122142 defer server .deinit ();
123143
124144 server .run (address , opts .timeout ) catch | err | {
0 commit comments