main: handle various forms of process termination more safely
This attempts to solve the problem where, if the rotator is actively rotating and the program is killed, the LabJack will not be reset and the rotator will keep running. We install various signal handlers to try to catch common cases (ctrl+c, terminal getting closed out from under us). There are still ways to end the process that leave the LabJack running (such as if it crashes, though there are currently no known crashes), but I don't think it's possible to completely avoid that.
This commit is contained in:
parent
c8cfc95938
commit
43692d8247
@ -10,7 +10,7 @@ const log = std.log.scoped(.RotCtl);
|
||||
|
||||
writer: std.io.BufferedWriter(512, std.net.Stream.Writer),
|
||||
running: bool,
|
||||
rotator: YaesuController,
|
||||
rotator: *YaesuController,
|
||||
|
||||
pub fn run(allocator: std.mem.Allocator) !void {
|
||||
// var server = std.net.StreamServer.init(.{ .reuse_address = true });
|
||||
@ -30,7 +30,7 @@ pub fn run(allocator: std.mem.Allocator) !void {
|
||||
var interface: RotCtl = .{
|
||||
.writer = undefined,
|
||||
.running = true,
|
||||
.rotator = try YaesuController.init(allocator),
|
||||
.rotator = try YaesuController.create(allocator),
|
||||
};
|
||||
|
||||
while (interface.running) {
|
||||
|
@ -8,6 +8,8 @@ const log = std.log.scoped(.yaesu_controller);
|
||||
|
||||
const YaesuController = @This();
|
||||
|
||||
pub var singleton: ?*YaesuController = null;
|
||||
|
||||
control_thread: std.Thread,
|
||||
lock: *std.Thread.Mutex,
|
||||
controller: *const Controller,
|
||||
@ -23,7 +25,7 @@ pub const CalibrationRoutine = enum {
|
||||
};
|
||||
|
||||
pub fn calibrate(allocator: std.mem.Allocator, routine: CalibrationRoutine) !void {
|
||||
const controller = try YaesuController.init(allocator);
|
||||
const controller = try YaesuController.create(allocator);
|
||||
defer {
|
||||
controller.quit();
|
||||
controller.control_thread.join();
|
||||
@ -35,7 +37,12 @@ pub fn calibrate(allocator: std.mem.Allocator, routine: CalibrationRoutine) !voi
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) !YaesuController {
|
||||
pub fn create(allocator: std.mem.Allocator) !*YaesuController {
|
||||
if (singleton) |_| {
|
||||
log.err("Controller singleton already exists.", .{});
|
||||
return error.AlreadyInitialized;
|
||||
}
|
||||
|
||||
const controller = try allocator.create(Controller);
|
||||
errdefer allocator.destroy(controller);
|
||||
controller.* = try Controller.init(allocator);
|
||||
@ -43,11 +50,16 @@ pub fn init(allocator: std.mem.Allocator) !YaesuController {
|
||||
// do this in the main thread so we can throw the error about it synchronously.
|
||||
try controller.connectLabjack();
|
||||
|
||||
return .{
|
||||
const self = try allocator.create(YaesuController);
|
||||
errdefer allocator.destroy(self);
|
||||
self.* = .{
|
||||
.control_thread = try std.Thread.spawn(.{}, runController, .{controller}),
|
||||
.lock = &controller.lock,
|
||||
.controller = controller,
|
||||
};
|
||||
|
||||
singleton = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
fn inRange(request: f64, comptime dof: enum { azimuth, elevation }) bool {
|
||||
|
53
src/main.zig
53
src/main.zig
@ -10,6 +10,45 @@ const udev = @import("udev_rules");
|
||||
|
||||
const log = std.log.scoped(.main);
|
||||
|
||||
fn die() noreturn {
|
||||
if (YaesuController.singleton) |controller| {
|
||||
controller.quit();
|
||||
controller.control_thread.join();
|
||||
}
|
||||
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
fn posixSignalHandler(signal: c_int) callconv(.C) void {
|
||||
_ = signal;
|
||||
die();
|
||||
}
|
||||
|
||||
fn windowsEventHandler(code: std.os.windows.DWORD) callconv(std.os.windows.WINAPI) std.os.windows.BOOL {
|
||||
_ = code;
|
||||
die();
|
||||
}
|
||||
|
||||
fn addAbortHandler() !void {
|
||||
if (comptime builtin.os.tag == .windows) {
|
||||
try std.os.windows.SetConsoleCtrlHandler(windowsEventHandler, true);
|
||||
} else {
|
||||
const action = std.posix.Sigaction{
|
||||
.handler = .{ .handler = posixSignalHandler },
|
||||
.mask = std.posix.empty_sigset,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
for ([_]u6{
|
||||
std.posix.SIG.INT,
|
||||
std.posix.SIG.HUP,
|
||||
std.posix.SIG.QUIT,
|
||||
}) |sig| {
|
||||
try std.posix.sigaction(sig, &action, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn printStderr(comptime fmt: []const u8, args: anytype) void {
|
||||
std.debug.print(fmt ++ "\n", args);
|
||||
}
|
||||
@ -66,9 +105,14 @@ pub fn main() !u8 {
|
||||
|
||||
defer Config.deinit();
|
||||
|
||||
addAbortHandler() catch {
|
||||
log.err("Could not install quit handler.", .{});
|
||||
return 1;
|
||||
};
|
||||
|
||||
RotCtl.run(allocator) catch |err| {
|
||||
log.err("rotator controller ceased unexpectedly! {s}", .{@errorName(err)});
|
||||
return 1;
|
||||
die();
|
||||
};
|
||||
} else if (std.mem.eql(u8, args[1], commands.calibrate)) {
|
||||
if (args.len < 3 or args.len > 4) {
|
||||
@ -86,9 +130,14 @@ pub fn main() !u8 {
|
||||
return 1;
|
||||
};
|
||||
|
||||
addAbortHandler() catch {
|
||||
log.err("Could not install quit handler.", .{});
|
||||
return 1;
|
||||
};
|
||||
|
||||
YaesuController.calibrate(allocator, routine) catch |err| {
|
||||
log.err("Calibration failed: {s}", .{@errorName(err)});
|
||||
return 1;
|
||||
die();
|
||||
};
|
||||
} else if (std.mem.eql(u8, args[1], commands.help)) {
|
||||
if (args.len != 3) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user