aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <ifreund@ifreund.xyz>2020-07-05 22:49:17 +0200
committerIsaac Freund <ifreund@ifreund.xyz>2020-07-05 22:49:17 +0200
commit341fe1e977cd44164f238030acc03bf7426f179d (patch)
tree5f858f4cba1d9f44fb45e7b8c34f82dbb5aae84c
parent3752a7879bb0d34d845470bc3a9face55662292a (diff)
downloadriver-341fe1e977cd44164f238030acc03bf7426f179d.tar.gz
river-341fe1e977cd44164f238030acc03bf7426f179d.tar.xz
code: handle out of memory as well as possible
-rw-r--r--build.zig4
-rw-r--r--river/Decoration.zig14
-rw-r--r--river/DecorationManager.zig8
-rw-r--r--river/InputManager.zig4
-rw-r--r--river/LayerSurface.zig5
-rw-r--r--river/Root.zig12
-rw-r--r--river/Seat.zig28
-rw-r--r--river/Server.zig14
-rw-r--r--river/XdgPopup.zig5
-rw-r--r--river/XdgToplevel.zig5
10 files changed, 55 insertions, 44 deletions
diff --git a/build.zig b/build.zig
index 20e1ae2..8a9572b 100644
--- a/build.zig
+++ b/build.zig
@@ -130,7 +130,7 @@ const ScanProtocolsStep = struct {
step: std.build.Step,
fn create(builder: *std.build.Builder) *ScanProtocolsStep {
- const self = builder.allocator.create(ScanProtocolsStep) catch unreachable;
+ const self = builder.allocator.create(ScanProtocolsStep) catch @panic("out of memory");
self.* = init(builder);
return self;
}
@@ -225,7 +225,7 @@ const ScdocStep = struct {
step: std.build.Step,
fn create(builder: *std.build.Builder) *ScdocStep {
- const self = builder.allocator.create(ScdocStep) catch unreachable;
+ const self = builder.allocator.create(ScdocStep) catch @panic("out of memory");
self.* = init(builder);
return self;
}
diff --git a/river/Decoration.zig b/river/Decoration.zig
index 863ae3f..44f48c2 100644
--- a/river/Decoration.zig
+++ b/river/Decoration.zig
@@ -22,10 +22,6 @@ const std = @import("std");
const c = @import("c.zig");
const util = @import("util.zig");
-const DecorationManager = @import("DecorationManager.zig");
-
-// TODO: this needs to listen for destroy and free nodes from the deco list
-decoration_manager: *DecorationManager,
wlr_xdg_toplevel_decoration: *c.wlr_xdg_toplevel_decoration_v1,
listen_destroy: c.wl_listener,
@@ -33,10 +29,8 @@ listen_request_mode: c.wl_listener,
pub fn init(
self: *Self,
- decoration_manager: *DecorationManager,
wlr_xdg_toplevel_decoration: *c.wlr_xdg_toplevel_decoration_v1,
) void {
- self.decoration_manager = decoration_manager;
self.wlr_xdg_toplevel_decoration = wlr_xdg_toplevel_decoration;
self.listen_destroy.notify = handleDestroy;
@@ -50,17 +44,13 @@ pub fn init(
fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
- const node = @fieldParentPtr(std.SinglyLinkedList(Self).Node, "data", self);
-
- self.decoration_manager.decorations.remove(node);
- util.gpa.destroy(node);
+ util.gpa.destroy(self);
}
fn handleRequestMode(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const self = @fieldParentPtr(Self, "listen_request_mode", listener.?);
- // TODO: we might need to take this configure serial and do a transaction
_ = c.wlr_xdg_toplevel_decoration_v1_set_mode(
self.wlr_xdg_toplevel_decoration,
- c.wlr_xdg_toplevel_decoration_v1_mode.WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE,
+ .WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE,
);
}
diff --git a/river/DecorationManager.zig b/river/DecorationManager.zig
index 2eb1509..b44dcef 100644
--- a/river/DecorationManager.zig
+++ b/river/DecorationManager.zig
@@ -46,7 +46,9 @@ fn handleNewToplevelDecoration(listener: ?*c.wl_listener, data: ?*c_void) callco
const self = @fieldParentPtr(Self, "listen_new_toplevel_decoration", listener.?);
const wlr_xdg_toplevel_decoration = util.voidCast(c.wlr_xdg_toplevel_decoration_v1, data.?);
- const node = self.decorations.allocateNode(util.gpa) catch unreachable;
- node.data.init(self, wlr_xdg_toplevel_decoration);
- self.decorations.prepend(node);
+ const decoration = util.gpa.create(Decoration) catch {
+ c.wl_resource_post_no_memory(wlr_xdg_toplevel_decoration.resource);
+ return;
+ };
+ decoration.init(wlr_xdg_toplevel_decoration);
}
diff --git a/river/InputManager.zig b/river/InputManager.zig
index 10293ea..80fd9e8 100644
--- a/river/InputManager.zig
+++ b/river/InputManager.zig
@@ -140,7 +140,5 @@ fn handleNewInput(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const device = util.voidCast(c.wlr_input_device, data.?);
// TODO: suport multiple seats
- if (self.seats.first) |seat_node| {
- seat_node.data.addDevice(device) catch unreachable;
- }
+ self.default_seat.addDevice(device);
}
diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig
index 97cf4bc..354173f 100644
--- a/river/LayerSurface.zig
+++ b/river/LayerSurface.zig
@@ -191,6 +191,9 @@ fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?);
// This will free itself on destroy
- var xdg_popup = util.gpa.create(XdgPopup) catch unreachable;
+ var xdg_popup = util.gpa.create(XdgPopup) catch {
+ c.wl_resource_post_no_memory(wlr_xdg_popup.resource);
+ return;
+ };
xdg_popup.init(self.output, &self.box, wlr_xdg_popup);
}
diff --git a/river/Root.zig b/river/Root.zig
index 381ce89..b93ed8a 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -86,13 +86,19 @@ pub fn deinit(self: *Self) void {
c.wlr_output_layout_destroy(self.wlr_output_layout);
+ // This literally cannot fail, but for some reason returns 0
if (c.wl_event_source_remove(self.transaction_timer) < 0) unreachable;
}
pub fn addOutput(self: *Self, wlr_output: *c.wlr_output) void {
- // TODO: Handle failure
- const node = self.outputs.allocateNode(util.gpa) catch unreachable;
- node.data.init(self, wlr_output) catch unreachable;
+ const node = self.outputs.allocateNode(util.gpa) catch {
+ c.wlr_output_destroy(wlr_output);
+ return;
+ };
+ node.data.init(self, wlr_output) catch {
+ c.wlr_output_destroy(wlr_output);
+ return;
+ };
self.outputs.append(node);
// if we previously had no real outputs, move focus from the noop output
diff --git a/river/Seat.zig b/river/Seat.zig
index f1991f9..4850da7 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -157,9 +157,7 @@ pub fn focus(self: *Self, _view: ?*View) void {
}
} else {
// The view is not in the stack, so allocate a new node and prepend it
- const new_focus_node = util.gpa.create(
- ViewStack(*View).Node,
- ) catch unreachable;
+ const new_focus_node = util.gpa.create(ViewStack(*View).Node) catch return;
new_focus_node.view = view_to_focus;
self.focus_stack.push(new_focus_node);
}
@@ -305,30 +303,32 @@ pub fn handleMapping(self: *Self, keysym: c.xkb_keysym_t, modifiers: u32) bool {
/// Add a newly created input device to the seat and update the reported
/// capabilities.
-pub fn addDevice(self: *Self, device: *c.wlr_input_device) !void {
+pub fn addDevice(self: *Self, device: *c.wlr_input_device) void {
switch (device.type) {
- .WLR_INPUT_DEVICE_KEYBOARD => self.addKeyboard(device) catch unreachable,
+ .WLR_INPUT_DEVICE_KEYBOARD => self.addKeyboard(device) catch return,
.WLR_INPUT_DEVICE_POINTER => self.addPointer(device),
- else => {},
+ else => return,
}
// We need to let the wlr_seat know what our capabilities are, which is
// communiciated to the client. We always have a cursor, even if
// there are no pointer devices, so we always include that capability.
var caps = @intCast(u32, c.WL_SEAT_CAPABILITY_POINTER);
- // if list not empty
- if (self.keyboards.len > 0) {
- caps |= @intCast(u32, c.WL_SEAT_CAPABILITY_KEYBOARD);
- }
+ if (self.keyboards.len > 0) caps |= @intCast(u32, c.WL_SEAT_CAPABILITY_KEYBOARD);
c.wlr_seat_set_capabilities(self.wlr_seat, caps);
}
fn addKeyboard(self: *Self, device: *c.wlr_input_device) !void {
- c.wlr_seat_set_keyboard(self.wlr_seat, device);
-
- const node = try util.gpa.create(std.TailQueue(Keyboard).Node);
- try node.data.init(self, device);
+ const node = try self.keyboards.allocateNode(util.gpa);
+ node.data.init(self, device) catch |err| {
+ switch (err) {
+ error.CreateXkbContextError => log.err(.keyboard, "Failed to create XKB context", .{}),
+ error.CreateXkbKeymapError => log.err(.keyboard, "Failed to create XKB keymap", .{}),
+ }
+ return;
+ };
self.keyboards.append(node);
+ c.wlr_seat_set_keyboard(self.wlr_seat, device);
}
fn addPointer(self: Self, device: *c.struct_wlr_input_device) void {
diff --git a/river/Server.zig b/river/Server.zig
index 90f6b19..0621a58 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -180,7 +180,10 @@ fn handleNewXdgSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) v
// The View will add itself to the output's view stack on map
const output = self.input_manager.default_seat.focused_output;
- const node = util.gpa.create(ViewStack(View).Node) catch unreachable;
+ const node = util.gpa.create(ViewStack(View).Node) catch {
+ c.wl_resource_post_no_memory(wlr_xdg_surface.resource);
+ return;
+ };
node.view.init(output, output.current.tags, wlr_xdg_surface);
}
@@ -230,7 +233,10 @@ fn handleNewLayerSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C)
// The layer surface will add itself to the proper list of the output on map
const output = util.voidCast(Output, wlr_layer_surface.output.*.data.?);
- const node = util.gpa.create(std.TailQueue(LayerSurface).Node) catch unreachable;
+ const node = util.gpa.create(std.TailQueue(LayerSurface).Node) catch {
+ c.wl_resource_post_no_memory(wlr_layer_surface.resource);
+ return;
+ };
node.data.init(output, wlr_layer_surface);
}
@@ -242,7 +248,7 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(
log.debug(.server, "new unmanaged xwayland surface", .{});
// The unmanged surface will add itself to the list of unmanaged views
// in Root when it is mapped.
- const node = util.gpa.create(std.TailQueue(XwaylandUnmanaged).Node) catch unreachable;
+ const node = util.gpa.create(std.TailQueue(XwaylandUnmanaged).Node) catch return;
node.data.init(&self.root, wlr_xwayland_surface);
return;
}
@@ -255,6 +261,6 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(
// The View will add itself to the output's view stack on map
const output = self.input_manager.default_seat.focused_output;
- const node = util.gpa.create(ViewStack(View).Node) catch unreachable;
+ const node = util.gpa.create(ViewStack(View).Node) catch return;
node.view.init(output, output.current.tags, wlr_xwayland_surface);
}
diff --git a/river/XdgPopup.zig b/river/XdgPopup.zig
index b4e50cd..b966a45 100644
--- a/river/XdgPopup.zig
+++ b/river/XdgPopup.zig
@@ -76,6 +76,9 @@ fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?);
// This will free itself on destroy
- var xdg_popup = util.gpa.create(Self) catch unreachable;
+ var xdg_popup = util.gpa.create(Self) catch {
+ c.wl_resource_post_no_memory(wlr_xdg_popup.resource);
+ return;
+ };
xdg_popup.init(self.output, self.parent_box, wlr_xdg_popup);
}
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index b818bbb..2ef46d3 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -253,7 +253,10 @@ fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?);
// This will free itself on destroy
- var xdg_popup = util.gpa.create(XdgPopup) catch unreachable;
+ var xdg_popup = util.gpa.create(XdgPopup) catch {
+ c.wl_resource_post_no_memory(wlr_xdg_popup.resource);
+ return;
+ };
xdg_popup.init(self.view.output, &self.view.current.box, wlr_xdg_popup);
}