+static void ipc_client_timeout(EV_P_ ev_timer *w, int revents);
+static void ipc_socket_writeable_cb(EV_P_ struct ev_io *w, int revents);
+
+static ev_tstamp kill_timeout = 10.0;
+
+void ipc_set_kill_timeout(ev_tstamp new) {
+ kill_timeout = new;
+}
+
+/*
+ * Try to write the contents of the pending buffer to the client's subscription
+ * socket. Will set, reset or clear the timeout and io callbacks depending on
+ * the result of the write operation.
+ *
+ */
+static void ipc_push_pending(ipc_client *client) {
+ const ssize_t result = writeall_nonblock(client->fd, client->buffer, client->buffer_size);
+ if (result < 0) {
+ return;
+ }
+
+ if ((size_t)result == client->buffer_size) {
+ /* Everything was written successfully: clear the timer and stop the io
+ * callback. */
+ FREE(client->buffer);
+ client->buffer_size = 0;
+ if (client->timeout) {
+ ev_timer_stop(main_loop, client->timeout);
+ FREE(client->timeout);
+ }
+ ev_io_stop(main_loop, client->callback);
+ return;
+ }
+
+ /* Otherwise, make sure that the io callback is enabled and create a new
+ * timer if needed. */
+ ev_io_start(main_loop, client->callback);
+
+ if (!client->timeout) {
+ struct ev_timer *timeout = scalloc(1, sizeof(struct ev_timer));
+ ev_timer_init(timeout, ipc_client_timeout, kill_timeout, 0.);
+ timeout->data = client;
+ client->timeout = timeout;
+ ev_set_priority(timeout, EV_MINPRI);
+ ev_timer_start(main_loop, client->timeout);
+ } else if (result > 0) {
+ /* Keep the old timeout when nothing is written. Otherwise, we would
+ * keep a dead connection by continuously renewing its timeouts. */
+ ev_timer_stop(main_loop, client->timeout);
+ ev_timer_set(client->timeout, kill_timeout, 0.0);
+ ev_timer_start(main_loop, client->timeout);
+ }
+ if (result == 0) {
+ return;
+ }
+
+ /* Shift the buffer to the left and reduce the allocated space. */
+ client->buffer_size -= (size_t)result;
+ memmove(client->buffer, client->buffer + result, client->buffer_size);
+ client->buffer = srealloc(client->buffer, client->buffer_size);
+}
+