knot_pkt_t *query = knot_pkt_new(buf->base + 2, nbytes, worker->mm);
query->max_size = sizeof(worker->bufs.wire);
- worker_exec(worker, (uv_handle_t *)handle, query, NULL);
+ int ret = worker_exec(worker, (uv_handle_t *)handle, query, NULL);
+ if (ret == 0) {
+ /* Push - pull, stop reading from this handle until
+ * the task is finished. Since the handle has no track of the
+ * pending tasks, it might be freed before the task finishes
+ * leading various errors. */
+ uv_unref((uv_handle_t *)handle);
+ io_stop_read((uv_handle_t *)handle);
+ }
knot_pkt_free(&query);
}
static void qr_task_free(uv_handle_t *handle)
{
struct qr_task *task = handle->data;
+ /* Return handle to the event loop in case
+ * it was exclusively taken by this task. */
+ if (!uv_has_ref(task->source.handle)) {
+ uv_ref(task->source.handle);
+ io_start_read(task->source.handle);
+ }
mp_delete(task->req.pool.ctx);
}
static int qr_task_finalize(struct qr_task *task, int state)
{
kr_resolve_finish(&task->req, state);
- qr_task_send(task, task->source.handle, (struct sockaddr *)&task->source.addr, task->req.answer);
+ int ret = qr_task_send(task, task->source.handle, (struct sockaddr *)&task->source.addr, task->req.answer);
+ if (ret != 0) { /* Broken connection */
+ uv_close((uv_handle_t *)&task->timeout, qr_task_free);
+ }
return state == KNOT_STATE_DONE ? 0 : kr_error(EIO);
}