fix segfault

This commit is contained in:
Emil Lerch 2026-02-04 15:38:51 -08:00
parent 6f590b28b7
commit 580f6657b9
Signed by: lobo
GPG key ID: A7B62D657EF764F8
4 changed files with 33 additions and 23 deletions

View file

@ -9,8 +9,8 @@
.hash = "controlr-0.1.0-upFm0LtgAAAo85RiRDa0WmSrORIhAa5bCF8UdT9rDyUk", .hash = "controlr-0.1.0-upFm0LtgAAAo85RiRDa0WmSrORIhAa5bCF8UdT9rDyUk",
}, },
.lambda_zig = .{ .lambda_zig = .{
.url = "git+https://git.lerch.org/lobo/lambda-zig#f444697d93244425fa799023d0e7adf80ecaa1de", .url = "git+https://git.lerch.org/lobo/lambda-zig#5c36a2c979b0bd4f0cbda3d64fb997f341085bc9",
.hash = "lambda_zig-0.1.0-_G43_9VdAQBdYVii9jenUiYxPssqZudPv23LEJVA2W0b", .hash = "lambda_zig-0.1.0-_G43_2ReAQDdEirp5hBDtuKAtAPzWjleCp9nw524BCdZ",
}, },
.aws = .{ .aws = .{
.url = "git+https://git.lerch.org/lobo/aws-sdk-for-zig#5c7aed071f6251d53a1627080a21d604ff58f0a5", .url = "git+https://git.lerch.org/lobo/aws-sdk-for-zig#5c7aed071f6251d53a1627080a21d604ff58f0a5",

View file

@ -64,6 +64,9 @@ pub fn parseContext(json_value: json.Value) ?Context {
/// GET {apiEndpoint}/v2/devices/{deviceId}/settings/System.timeZone /// GET {apiEndpoint}/v2/devices/{deviceId}/settings/System.timeZone
/// Returns timezone name like "America/Los_Angeles" or null on failure. /// Returns timezone name like "America/Los_Angeles" or null on failure.
/// Caller owns the returned memory. /// Caller owns the returned memory.
///
/// NOTE: This function is currently not used because the API call takes ~1 second
/// which is too slow for our 3 second Lambda timeout. See resolveTimezone() in main.zig.
pub fn fetchTimezone( pub fn fetchTimezone(
allocator: Allocator, allocator: Allocator,
http_interface: homeassistant.HttpClientInterface, http_interface: homeassistant.HttpClientInterface,

View file

@ -251,7 +251,7 @@ pub const Client = struct {
base_url: []const u8, base_url: []const u8,
token: []const u8, token: []const u8,
http_interface: HttpClientInterface, http_interface: HttpClientInterface,
client: ?HttpClient = null, client: ?*HttpClient = null,
/// Normal initialization. If you are writing tests and need a mock /// Normal initialization. If you are writing tests and need a mock
/// implemenation for unit tests, use MockHttpClient with the initInterface /// implemenation for unit tests, use MockHttpClient with the initInterface
@ -261,7 +261,8 @@ pub const Client = struct {
base_url: []const u8, base_url: []const u8,
token: []const u8, token: []const u8,
) Client { ) Client {
var client = HttpClient.init(allocator); const client = allocator.create(HttpClient) catch @panic("OOM");
client.* = HttpClient.init(allocator);
return .{ return .{
.allocator = allocator, .allocator = allocator,
.base_url = base_url, .base_url = base_url,
@ -288,7 +289,10 @@ pub const Client = struct {
} }
pub fn deinit(self: Client) void { pub fn deinit(self: Client) void {
if (self.client) |c| c.deinit(); if (self.client) |c| {
c.deinit();
self.allocator.destroy(c);
}
} }
/// Fetch all entity states from Home Assistant /// Fetch all entity states from Home Assistant
pub fn getStates(self: *Client) !struct { entities: []Entity, parsed: json.Parsed(json.Value) } { pub fn getStates(self: *Client) !struct { entities: []Entity, parsed: json.Parsed(json.Value) } {

View file

@ -55,7 +55,6 @@ pub fn main() !u8 {
/// Main Alexa request handler /// Main Alexa request handler
fn handler(allocator: std.mem.Allocator, event_data: []const u8, config: Config) anyerror![]const u8 { fn handler(allocator: std.mem.Allocator, event_data: []const u8, config: Config) anyerror![]const u8 {
log.info("Received Alexa request: {d} bytes", .{event_data.len});
// Parse the Alexa request // Parse the Alexa request
const parsed = json.parseFromSlice(json.Value, allocator, event_data, .{}) catch |err| { const parsed = json.parseFromSlice(json.Value, allocator, event_data, .{}) catch |err| {
@ -354,27 +353,31 @@ fn extractSlotNumber(slots: ?json.Value, slot_name: []const u8) ?f32 {
} }
/// Resolve the UTC offset for timezone conversion. /// Resolve the UTC offset for timezone conversion.
/// In Lambda mode: tries Alexa Settings API, then falls back to local timezone. /// In Lambda mode: uses TZ env var (Alexa API lookup disabled - too slow ~1s).
/// In local mode: uses TZ env var or /etc/timezone. /// In local mode: uses TZ env var or /etc/timezone.
fn resolveTimezone(allocator: std.mem.Allocator, parsed_value: json.Value, config: Config) ?i32 { fn resolveTimezone(allocator: std.mem.Allocator, parsed_value: json.Value, config: Config) ?i32 {
// First try to get timezone from Alexa context (Lambda mode) _ = parsed_value;
if (alexa.parseContext(parsed_value)) |context| { _ = config;
// Need HTTP client for Alexa API
const ha_url = config.home_assistant_url orelse return resolveLocalTimezone(allocator);
const ha_token = config.home_assistant_token orelse return resolveLocalTimezone(allocator);
var ha_client = homeassistant.Client.init(allocator, ha_url, ha_token); // NOTE: Alexa Settings API timezone lookup is disabled because it takes ~1 second
defer ha_client.deinit(); // which is too much of our 3 second Lambda timeout budget. Instead, we use the
// TZ environment variable set in Lambda configuration.
//
// To re-enable Alexa timezone lookup, uncomment the following block:
//
// if (alexa.parseContext(parsed_value)) |context| {
// const ha_url = config.home_assistant_url orelse return resolveLocalTimezone(allocator);
// const ha_token = config.home_assistant_token orelse return resolveLocalTimezone(allocator);
// var ha_client = homeassistant.Client.init(allocator, ha_url, ha_token);
// defer ha_client.deinit();
// if (alexa.fetchTimezone(allocator, ha_client.httpInterface(), context)) |tz_name| {
// defer allocator.free(tz_name);
// if (timezone.getUtcOffset(allocator, tz_name)) |offset| {
// return offset;
// }
// }
// }
if (alexa.fetchTimezone(allocator, ha_client.http_interface, context)) |tz_name| {
defer allocator.free(tz_name);
if (timezone.getUtcOffset(allocator, tz_name)) |offset| {
return offset;
}
}
}
// Fall back to local timezone
return resolveLocalTimezone(allocator); return resolveLocalTimezone(allocator);
} }