Skip to content
This repository was archived by the owner on Aug 26, 2024. It is now read-only.

Commit aec5a01

Browse files
author
jan.kneschke@oracle.com
committed
syncronize the async-queue operations (push/pop) with the notify-pipe-ops (send/recv)
- fixes the CPU burn as there was race-condition between the async-queuen and notify-pipe ops
1 parent ea13161 commit aec5a01

File tree

1 file changed

+40
-38
lines changed

1 file changed

+40
-38
lines changed

src/chassis-event-thread.c

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ void chassis_event_add_with_timeout(chassis *chas, struct event *ev, struct time
111111
op->type = CHASSIS_EVENT_OP_ADD;
112112
op->ev = ev;
113113
chassis_event_op_set_timeout(op, tv);
114-
g_async_queue_push(chas->threads->event_queue, op);
114+
115+
g_async_queue_lock(chas->threads->event_queue);
116+
g_async_queue_push_unlocked(chas->threads->event_queue, op);
115117

116118
/* ping the event handler */
117119
if (1 != (ret = send(chas->threads->event_notify_fds[1], C("."), 0))) {
@@ -129,16 +131,20 @@ void chassis_event_add_with_timeout(chassis *chas, struct event *ev, struct time
129131
case EWOULDBLOCK:
130132
#endif
131133
/* that's fine ... */
134+
g_debug("%s: send() to event-notify-pipe failed: %s (len = %d)",
135+
G_STRLOC,
136+
g_strerror(errno),
137+
g_async_queue_length_unlocked(chas->threads->event_queue));
132138
break;
133139
default:
134-
g_debug("%s: send() to event-notify-pipe failed: %s (len = %d)",
140+
g_critical("%s: send() to event-notify-pipe failed: %s (len = %d)",
135141
G_STRLOC,
136142
g_strerror(errno),
137-
g_async_queue_length(chas->threads->event_queue));
143+
g_async_queue_length_unlocked(chas->threads->event_queue));
138144
break;
139145
}
140146
}
141-
147+
g_async_queue_unlock(chas->threads->event_queue);
142148
}
143149

144150
/**
@@ -197,51 +203,47 @@ void chassis_event_handle(int G_GNUC_UNUSED event_fd, short G_GNUC_UNUSED events
197203
struct event_base *event_base = event_thread->event_base;
198204
chassis *chas = event_thread->chas;
199205
chassis_event_op_t *op;
200-
char ping[1024];
201-
guint received = 0;
202-
gssize removed = 0;
203206

204-
while ((op = g_async_queue_try_pop(chas->threads->event_queue))) {
205-
chassis_event_op_apply(op, event_base);
207+
do {
208+
char ping[1];
206209

207-
chassis_event_op_free(op);
208-
209-
received++;
210-
}
211-
212-
/* the pipe has one . per event, remove as many as we received
213-
*
214-
* but the remote end may have dropped .'s as the pipe was full. */
215-
while (received > 0 &&
216-
(removed = recv(event_thread->notify_fd, ping, MIN(received, sizeof(ping)), 0)) > 0) {
217-
received -= removed;
218-
}
210+
g_async_queue_lock(chas->threads->event_queue);
211+
if ((op = g_async_queue_try_pop_unlocked(chas->threads->event_queue))) {
212+
ssize_t ret;
213+
chassis_event_op_apply(op, event_base);
219214

220-
if (removed == -1) {
221-
/* we failed to pull .'s from the notify-queue */
222-
int last_errno;
215+
chassis_event_op_free(op);
216+
217+
if (1 != (ret = recv(event_thread->notify_fd, ping, 1, 0))) {
218+
/* we failed to pull .'s from the notify-queue */
219+
int last_errno;
223220

224221
#ifdef WIN32
225-
last_errno = WSAGetLastError();
222+
last_errno = WSAGetLastError();
226223
#else
227-
last_errno = errno;
224+
last_errno = errno;
228225
#endif
229226

230-
switch (last_errno) {
231-
case EAGAIN:
227+
switch (last_errno) {
228+
case EAGAIN:
232229
#if EAGAIN != EWOULDBLOCK
233-
case EWOULDBLOCK:
230+
case EWOULDBLOCK:
234231
#endif
235-
/* that's fine ... */
236-
break;
237-
default:
238-
g_debug("%s: recv() from event-notify-fd failed: %s (expected %d more)",
239-
G_STRLOC,
240-
g_strerror(last_errno),
241-
received);
242-
break;
232+
/* that's fine ... */
233+
g_debug("%s: recv() from event-notify-fd failed: %s",
234+
G_STRLOC,
235+
g_strerror(last_errno));
236+
break;
237+
default:
238+
g_critical("%s: recv() from event-notify-fd failed: %s",
239+
G_STRLOC,
240+
g_strerror(last_errno));
241+
break;
242+
}
243+
}
243244
}
244-
}
245+
g_async_queue_unlock(chas->threads->event_queue);
246+
} while (op); /* even if op is 'free()d' it still is != NULL */
245247
}
246248

247249
/**

0 commit comments

Comments
 (0)