Do not perform any python API calls in the I/O thread

This commit is contained in:
Kovid Goyal 2017-09-06 16:45:47 +05:30
parent 2c8f3b6d98
commit 76890a2b71
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -24,12 +24,6 @@ typedef struct {
} Child;
static const Child EMPTY_CHILD = {0};
#define FREE_CHILD(x) \
Py_CLEAR((x).screen); x = EMPTY_CHILD;
#define XREF_CHILD(x, OP) OP(x.screen);
#define INCREF_CHILD(x) XREF_CHILD(x, Py_INCREF)
#define DECREF_CHILD(x) XREF_CHILD(x, Py_DECREF)
#define screen_mutex(op, which) \
pthread_mutex_##op(&screen->which##_buf_lock);
#define children_mutex(op) \
@ -38,10 +32,10 @@ static const Child EMPTY_CHILD = {0};
static Child children[MAX_CHILDREN] = {{0}};
static Child scratch[MAX_CHILDREN] = {{0}};
static Child add_queue[MAX_CHILDREN] = {{0}};
static Child add_queue[MAX_CHILDREN] = {{0}}, remove_queue[MAX_CHILDREN] = {{0}};
static unsigned long dead_children[MAX_CHILDREN] = {0};
static size_t num_dead_children = 0;
static size_t add_queue_count = 0;
static size_t add_queue_count = 0, remove_queue_count = 0;
static struct pollfd fds[MAX_CHILDREN + EXTRA_FDS] = {{0}};
static pthread_mutex_t children_lock = {{0}};
static bool created = false, signal_received = false;
@ -50,6 +44,13 @@ static uint8_t drain_buf[1024];
// Main thread functions {{{
#define FREE_CHILD(x) \
Py_CLEAR((x).screen); x = EMPTY_CHILD;
#define XREF_CHILD(x, OP) OP(x.screen);
#define INCREF_CHILD(x) XREF_CHILD(x, Py_INCREF)
#define DECREF_CHILD(x) XREF_CHILD(x, Py_DECREF)
static PyObject *
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
ChildMonitor *self;
@ -89,10 +90,16 @@ dealloc(ChildMonitor* self) {
Py_CLEAR(self->death_notify);
Py_CLEAR(self->update_screen);
Py_CLEAR(self->timers);
for (size_t i = 0; i < self->count; i++) {
FREE_CHILD(children[i]);
}
Py_TYPE(self)->tp_free((PyObject*)self);
while (remove_queue_count) {
remove_queue_count--;
FREE_CHILD(remove_queue[remove_queue_count]);
}
while (add_queue_count) {
add_queue_count--;
FREE_CHILD(add_queue[add_queue_count]);
}
}
static void
@ -190,6 +197,10 @@ parse_input(ChildMonitor *self) {
if (t == NULL) PyErr_Print();
else Py_DECREF(t);
}
while (remove_queue_count) {
remove_queue_count--;
FREE_CHILD(remove_queue[remove_queue_count]);
}
size_t count = self->count;
bool sr = signal_received;
@ -237,6 +248,9 @@ mark_for_close(ChildMonitor *self, PyObject *args) {
Py_RETURN_NONE;
}
#undef FREE_CHILD
#undef INCREF_CHILD
#undef DECREF_CHILD
// }}}
@ -248,32 +262,32 @@ add_children(ChildMonitor *self) {
for (; add_queue_count > 0 && self->count < MAX_CHILDREN;) {
add_queue_count--;
children[self->count] = add_queue[add_queue_count];
fds[EXTRA_FDS + self->count].fd = add_queue[add_queue_count].fd;
add_queue[add_queue_count] = EMPTY_CHILD;
fds[EXTRA_FDS + self->count].fd = children[self->count].fd;
fds[EXTRA_FDS + self->count].events = POLLIN;
INCREF_CHILD(children[self->count]);
self->count++;
DECREF_CHILD(add_queue[add_queue_count]);
}
}
static inline bool
static inline void
remove_children(ChildMonitor *self) {
size_t count = 0;
if (self->count == 0) goto end;
for (ssize_t i = self->count - 1; i >= 0; i--) {
if (children[i].needs_removal) {
count++;
close(fds[EXTRA_FDS + i].fd);
FREE_CHILD(children[i]);
size_t num_to_right = self->count - 1 - i;
if (num_to_right > 0) {
memmove(children + i, children + i + 1, num_to_right * sizeof(Child));
if (self->count > 0) {
size_t count = 0;
for (ssize_t i = self->count - 1; i >= 0; i--) {
if (children[i].needs_removal) {
count++;
close(fds[EXTRA_FDS + i].fd);
remove_queue[remove_queue_count] = children[i];
remove_queue_count++;
children[i] = EMPTY_CHILD;
size_t num_to_right = self->count - 1 - i;
if (num_to_right > 0) {
memmove(children + i, children + i + 1, num_to_right * sizeof(Child));
}
}
}
self->count -= count;
}
self->count -= count;
end:
return count ? true : false;
}
@ -351,12 +365,12 @@ loop(ChildMonitor *self) {
bool has_more, data_received;
Screen *screen;
Py_BEGIN_ALLOW_THREADS;
while (LIKELY(!self->shutting_down)) {
children_mutex(lock);
remove_children(self);
add_children(self);
children_mutex(unlock);
Py_BEGIN_ALLOW_THREADS;
data_received = false;
for (i = 0; i < self->count + EXTRA_FDS; i++) fds[i].revents = 0;
for (i = 0; i < self->count; i++) {
@ -395,11 +409,13 @@ loop(ChildMonitor *self) {
}
}
if (data_received) glfwPostEmptyEvent();
Py_END_ALLOW_THREADS;
}
children_mutex(lock);
for (i = 0; i < self->count; i++) children[i].needs_removal = true;
remove_children(self);
for (i = 0; i < EXTRA_FDS; i++) close(fds[i].fd);
children_mutex(unlock);
Py_END_ALLOW_THREADS;
Py_RETURN_NONE;
}
// }}}