diff options
author | 2018-02-04 10:37:46 -0700 | |
---|---|---|
committer | 2018-02-04 12:31:07 -0700 | |
commit | a83bca6db5348033b21ebb4ed7bc189d39e2b0c4 (patch) | |
tree | ab10cd02219ad353a97794139e92e8801ce5871f /swaybar/event_loop.c | |
parent | Merge pull request #1579 from tmccombs/patch-1 (diff) | |
download | sway-a83bca6db5348033b21ebb4ed7bc189d39e2b0c4.tar.gz sway-a83bca6db5348033b21ebb4ed7bc189d39e2b0c4.tar.zst sway-a83bca6db5348033b21ebb4ed7bc189d39e2b0c4.zip |
Handle swaybar status line errors
The event loop API was redesigned to avoid race conditions as well.
Fixes #1583
Diffstat (limited to 'swaybar/event_loop.c')
-rw-r--r-- | swaybar/event_loop.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c index 0d1be1da..bde8203f 100644 --- a/swaybar/event_loop.c +++ b/swaybar/event_loop.c | |||
@@ -20,6 +20,19 @@ struct timer_item { | |||
20 | void *data; | 20 | void *data; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | enum state_item_flags { | ||
24 | ITEM_IS_FD, | ||
25 | ITEM_IS_TIMER, | ||
26 | }; | ||
27 | |||
28 | struct state_item { | ||
29 | enum state_item_flags flags; | ||
30 | union { | ||
31 | int fd; | ||
32 | timer_t timer; | ||
33 | } inner; | ||
34 | }; | ||
35 | |||
23 | static struct { | 36 | static struct { |
24 | // The order of each must be kept consistent | 37 | // The order of each must be kept consistent |
25 | struct { /* pollfd array */ | 38 | struct { /* pollfd array */ |
@@ -31,6 +44,9 @@ static struct { | |||
31 | 44 | ||
32 | // Timer list | 45 | // Timer list |
33 | list_t *timers; | 46 | list_t *timers; |
47 | |||
48 | // List of state changes at the end of each iteration | ||
49 | list_t *state; | ||
34 | } event_loop; | 50 | } event_loop; |
35 | 51 | ||
36 | void add_timer(timer_t timer, | 52 | void add_timer(timer_t timer, |
@@ -72,7 +88,7 @@ void add_event(int fd, short mask, | |||
72 | return; | 88 | return; |
73 | } | 89 | } |
74 | 90 | ||
75 | bool remove_event(int fd) { | 91 | static void _remove_event(int fd) { |
76 | int index = -1; | 92 | int index = -1; |
77 | for (int i = 0; i < event_loop.fds.length; ++i) { | 93 | for (int i = 0; i < event_loop.fds.length; ++i) { |
78 | if (event_loop.fds.items[i].fd == fd) { | 94 | if (event_loop.fds.items[i].fd == fd) { |
@@ -87,12 +103,16 @@ bool remove_event(int fd) { | |||
87 | sizeof(struct pollfd) * event_loop.fds.length - index); | 103 | sizeof(struct pollfd) * event_loop.fds.length - index); |
88 | 104 | ||
89 | list_del(event_loop.items, index); | 105 | list_del(event_loop.items, index); |
90 | return true; | ||
91 | } else { | ||
92 | return false; | ||
93 | } | 106 | } |
94 | } | 107 | } |
95 | 108 | ||
109 | void remove_event(int fd) { | ||
110 | struct state_item *item = malloc(sizeof(struct state_item)); | ||
111 | item->flags = ITEM_IS_FD; | ||
112 | item->inner.fd = fd; | ||
113 | list_add(event_loop.state, item); | ||
114 | } | ||
115 | |||
96 | static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { | 116 | static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { |
97 | const struct timer_item *timer_item = _timer_item; | 117 | const struct timer_item *timer_item = _timer_item; |
98 | const timer_t *timer = _timer; | 118 | const timer_t *timer = _timer; |
@@ -102,14 +122,19 @@ static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { | |||
102 | return -1; | 122 | return -1; |
103 | } | 123 | } |
104 | } | 124 | } |
105 | bool remove_timer(timer_t timer) { | 125 | static void _remove_timer(timer_t timer) { |
106 | int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); | 126 | int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); |
107 | if (index != -1) { | 127 | if (index != -1) { |
108 | free(event_loop.timers->items[index]); | 128 | free(event_loop.timers->items[index]); |
109 | list_del(event_loop.timers, index); | 129 | list_del(event_loop.timers, index); |
110 | return true; | ||
111 | } | 130 | } |
112 | return false; | 131 | } |
132 | |||
133 | void remove_timer(timer_t timer) { | ||
134 | struct state_item *item = malloc(sizeof(struct state_item)); | ||
135 | item->flags = ITEM_IS_TIMER; | ||
136 | item->inner.timer = timer; | ||
137 | list_add(event_loop.state, item); | ||
113 | } | 138 | } |
114 | 139 | ||
115 | void event_loop_poll() { | 140 | void event_loop_poll() { |
@@ -133,6 +158,19 @@ void event_loop_poll() { | |||
133 | item->cb(item->timer, item->data); | 158 | item->cb(item->timer, item->data); |
134 | } | 159 | } |
135 | } | 160 | } |
161 | |||
162 | // Remove all requested items from the event loop. We can't do this | ||
163 | // during normal operation, as it will cause race conditions. | ||
164 | for (int i = 0; i < event_loop.state->length; ++i) { | ||
165 | struct state_item *item = event_loop.state->items[i]; | ||
166 | if (item->flags == ITEM_IS_FD) { | ||
167 | _remove_event(item->inner.fd); | ||
168 | } else { | ||
169 | _remove_timer(item->inner.timer); | ||
170 | } | ||
171 | free(item); | ||
172 | } | ||
173 | event_loop.state->length = 0; // reset state list | ||
136 | } | 174 | } |
137 | 175 | ||
138 | void init_event_loop() { | 176 | void init_event_loop() { |
@@ -141,4 +179,5 @@ void init_event_loop() { | |||
141 | event_loop.fds.items = malloc(event_loop.fds.capacity * sizeof(struct pollfd)); | 179 | event_loop.fds.items = malloc(event_loop.fds.capacity * sizeof(struct pollfd)); |
142 | event_loop.items = create_list(); | 180 | event_loop.items = create_list(); |
143 | event_loop.timers = create_list(); | 181 | event_loop.timers = create_list(); |
182 | event_loop.state = create_list(); | ||
144 | } | 183 | } |