aboutsummaryrefslogtreecommitdiff
path: root/swaybar
diff options
context:
space:
mode:
authorFurkan Sahin <furkan-dev@proton.me>2018-04-21 14:38:34 +1200
committerFurkan Sahin <furkan-dev@proton.me>2018-04-21 14:38:34 +1200
commitf52cc20dfa2037f6ad6366f5b6590f712447d9f3 (patch)
treeb8b262da93dbd5b13d30190f86f3d82fe66e537a /swaybar
parente6d9c52caeac60a627727c208b6465c80210dd5b (diff)
Change remove_event logic
We defer the removal of entries until after the poll loop has finished. Otherwise we may end up adjusting the poll array while we're still reading from it, causing us to skip events.
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/event_loop.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c
index 1e0d426b..bc4053be 100644
--- a/swaybar/event_loop.c
+++ b/swaybar/event_loop.c
@@ -72,24 +72,18 @@ void add_event(int fd, short mask,
}
bool remove_event(int fd) {
- int index = -1;
+ /*
+ * Instead of removing events immediately, we mark them for deletion
+ * and clean them up later. This is so we can call remove_event inside
+ * an event callback safely.
+ */
for (int i = 0; i < event_loop.fds.length; ++i) {
if (event_loop.fds.items[i].fd == fd) {
- index = i;
+ event_loop.fds.items[i].fd = -1;
+ return true;
}
}
- if (index != -1) {
- free(event_loop.items->items[index]);
-
- --event_loop.fds.length;
- memmove(&event_loop.fds.items[index], &event_loop.fds.items[index + 1],
- sizeof(struct pollfd) * event_loop.fds.length - index);
-
- list_del(event_loop.items, index);
- return true;
- } else {
- return false;
- }
+ return false;
}
static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
@@ -126,6 +120,21 @@ void event_loop_poll() {
}
}
+ // Cleanup removed events
+ int end = 0;
+ int length = event_loop.fds.length;
+ for (int i = 0; i < length; ++i) {
+ if (event_loop.fds.items[i].fd == -1) {
+ free(event_loop.items->items[i]);
+ list_del(event_loop.items, i);
+ --event_loop.fds.length;
+ } else if (end != i) {
+ event_loop.fds.items[end++] = event_loop.fds.items[i];
+ } else {
+ end = i + 1;
+ }
+ }
+
// check timers
// not tested, but seems to work
for (int i = 0; i < event_loop.timers->length; ++i) {