aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-01-07 14:58:28 +0100
committerIsaac Freund <mail@isaacfreund.com>2023-01-07 14:58:28 +0100
commitf511a34dedfd5b3bed5bd9d078530adf4c26c83c (patch)
tree396e8b5e1424fc5cd44bf1e547ceefeea2c2b973
parentdf2fc30238fe445cf04aaf64d0b906195129f726 (diff)
downloadriver-f511a34dedfd5b3bed5bd9d078530adf4c26c83c.tar.gz
river-f511a34dedfd5b3bed5bd9d078530adf4c26c83c.tar.xz
session-lock: fix assertion failure due to race
There's currently a potential race in the implementation that can be hit during unlocking. This is not a security vulnerability, but it does cause the compositor to crash due to a failed assertion. This commit simplifies the code and fixes the race as well as tightening up the assertions around this state/control flow even further.
-rw-r--r--river/Output.zig4
-rw-r--r--river/render.zig13
2 files changed, 12 insertions, 5 deletions
diff --git a/river/Output.zig b/river/Output.zig
index 0d5a541..b14247a 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -530,7 +530,7 @@ fn handlePresent(
const self = @fieldParentPtr(Self, "present", listener);
switch (self.lock_render_state) {
- .unlocked => return,
+ .unlocked => assert(server.lock_manager.state != .locked),
.pending_blank, .pending_lock_surface => {
if (!event.presented) {
self.lock_render_state = .unlocked;
@@ -548,7 +548,7 @@ fn handlePresent(
server.lock_manager.maybeLock();
}
},
- .blanked, .lock_surface => unreachable,
+ .blanked, .lock_surface => {},
}
}
diff --git a/river/render.zig b/river/render.zig
index a238cd9..6c1280c 100644
--- a/river/render.zig
+++ b/river/render.zig
@@ -98,10 +98,17 @@ pub fn renderOutput(output: *Output) void {
return;
};
- if (output.lock_surface == null) {
- output.lock_render_state = .pending_blank;
+ if (server.lock_manager.state == .locked) {
+ switch (output.lock_render_state) {
+ .unlocked, .pending_blank, .pending_lock_surface => unreachable,
+ .blanked, .lock_surface => {},
+ }
} else {
- output.lock_render_state = .pending_lock_surface;
+ if (output.lock_surface == null) {
+ output.lock_render_state = .pending_blank;
+ } else {
+ output.lock_render_state = .pending_lock_surface;
+ }
}
return;