summaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Scott Anderson <scott@anderso.nz>2018-04-21 14:38:34 +1200
committerLibravatar Scott Anderson <scott@anderso.nz>2018-04-21 14:38:34 +1200
commit9a3fb33e33b2503809d9d3a1b0d10c21bc112a80 (patch)
treeb8b262da93dbd5b13d30190f86f3d82fe66e537a /swaybar
parentAlways send POLLHUP and POLLERR with event loop (diff)
downloadsway-9a3fb33e33b2503809d9d3a1b0d10c21bc112a80.tar.gz
sway-9a3fb33e33b2503809d9d3a1b0d10c21bc112a80.tar.zst
sway-9a3fb33e33b2503809d9d3a1b0d10c21bc112a80.zip
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,
72} 72}
73 73
74bool remove_event(int fd) { 74bool remove_event(int fd) {
75 int index = -1; 75 /*
76 * Instead of removing events immediately, we mark them for deletion
77 * and clean them up later. This is so we can call remove_event inside
78 * an event callback safely.
79 */
76 for (int i = 0; i < event_loop.fds.length; ++i) { 80 for (int i = 0; i < event_loop.fds.length; ++i) {
77 if (event_loop.fds.items[i].fd == fd) { 81 if (event_loop.fds.items[i].fd == fd) {
78 index = i; 82 event_loop.fds.items[i].fd = -1;
83 return true;
79 } 84 }
80 } 85 }
81 if (index != -1) { 86 return false;
82 free(event_loop.items->items[index]);
83
84 --event_loop.fds.length;
85 memmove(&event_loop.fds.items[index], &event_loop.fds.items[index + 1],
86 sizeof(struct pollfd) * event_loop.fds.length - index);
87
88 list_del(event_loop.items, index);
89 return true;
90 } else {
91 return false;
92 }
93} 87}
94 88
95static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { 89static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
@@ -126,6 +120,21 @@ void event_loop_poll() {
126 } 120 }
127 } 121 }
128 122
123 // Cleanup removed events
124 int end = 0;
125 int length = event_loop.fds.length;
126 for (int i = 0; i < length; ++i) {
127 if (event_loop.fds.items[i].fd == -1) {
128 free(event_loop.items->items[i]);
129 list_del(event_loop.items, i);
130 --event_loop.fds.length;
131 } else if (end != i) {
132 event_loop.fds.items[end++] = event_loop.fds.items[i];
133 } else {
134 end = i + 1;
135 }
136 }
137
129 // check timers 138 // check timers
130 // not tested, but seems to work 139 // not tested, but seems to work
131 for (int i = 0; i < event_loop.timers->length; ++i) { 140 for (int i = 0; i < event_loop.timers->length; ++i) {