|
Tomas Hozza |
3ddaff |
From 527e971a732d645d411df842ec4f8c401248ca0c Mon Sep 17 00:00:00 2001
|
|
Tomas Hozza |
3ddaff |
From: Tomas Hozza <thozza@redhat.com>
|
|
Tomas Hozza |
3ddaff |
Date: Fri, 18 Oct 2013 10:47:21 +0200
|
|
Tomas Hozza |
3ddaff |
Subject: [PATCH] Dynamically allocate send buffers when sending query
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
This prevents race condition, when the same buffer could be added into
|
|
Tomas Hozza |
3ddaff |
multiple bufferlists. One case when this happens is when timeout of sent
|
|
Tomas Hozza |
3ddaff |
UDP query expires before send_done() is called.
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
New function isc_buffer_cloneused() has been added, so dynamically
|
|
Tomas Hozza |
3ddaff |
allocated copy of used region of a buffer can be created easily.
|
|
Tomas Hozza |
3ddaff |
(It should be added into buffer.c but to prevent API change it is
|
|
Tomas Hozza |
3ddaff |
in dighost.c)
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
All functions creating a send socket event with send_done() callback
|
|
Tomas Hozza |
3ddaff |
have been modified to make dynamically allocated copies of every buffer
|
|
Tomas Hozza |
3ddaff |
added into query->sendlist. This list is then bounded to the send socket
|
|
Tomas Hozza |
3ddaff |
event. This way the same buffer can not be anymore added to the same
|
|
Tomas Hozza |
3ddaff |
bufferlist. Previously allocated copies of buffers are freed in
|
|
Tomas Hozza |
3ddaff |
send_done() callback.
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
Signed-off-by: Tomas Hozza <thozza@redhat.com>
|
|
Tomas Hozza |
3ddaff |
---
|
|
Tomas Hozza |
3ddaff |
bin/dig/dighost.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
Tomas Hozza |
3ddaff |
1 file changed, 53 insertions(+), 5 deletions(-)
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
|
|
Tomas Hozza |
3ddaff |
index 0d41529..7899c49 100644
|
|
Tomas Hozza |
3ddaff |
--- a/bin/dig/dighost.c
|
|
Tomas Hozza |
3ddaff |
+++ b/bin/dig/dighost.c
|
|
Tomas Hozza |
3ddaff |
@@ -362,6 +362,36 @@ struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
|
|
Tomas Hozza |
3ddaff |
"isc_mutex_unlock");\
|
|
Tomas Hozza |
3ddaff |
}
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
+static isc_result_t
|
|
Tomas Hozza |
3ddaff |
+isc_buffer_cloneused(isc_mem_t *mctx, isc_buffer_t *src_buffer, isc_buffer_t **dynbuffer) {
|
|
Tomas Hozza |
3ddaff |
+ /*
|
|
Tomas Hozza |
3ddaff |
+ * Make 'dynbuffer' refer to a dynamically allocated copy of used region of 'src_buffer'.
|
|
Tomas Hozza |
3ddaff |
+ */
|
|
Tomas Hozza |
3ddaff |
+ isc_result_t result;
|
|
Tomas Hozza |
3ddaff |
+ isc_region_t used_region;
|
|
Tomas Hozza |
3ddaff |
+ isc_buffer_t *tmpbuf = NULL;
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
+ REQUIRE(dynbuffer != NULL);
|
|
Tomas Hozza |
3ddaff |
+ REQUIRE(*dynbuffer == NULL);
|
|
Tomas Hozza |
3ddaff |
+ REQUIRE(src_buffer != NULL);
|
|
Tomas Hozza |
3ddaff |
+ REQUIRE(ISC_BUFFER_VALID(src_buffer));
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
+ result = isc_buffer_allocate(mctx, &tmpbuf, src_buffer->length);
|
|
Tomas Hozza |
3ddaff |
+ if (result != ISC_R_SUCCESS)
|
|
Tomas Hozza |
3ddaff |
+ return result;
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
+ isc_buffer_usedregion(src_buffer, &used_region);
|
|
Tomas Hozza |
3ddaff |
+ result = isc_buffer_copyregion(tmpbuf, &used_region);
|
|
Tomas Hozza |
3ddaff |
+ if (result != ISC_R_SUCCESS) {
|
|
Tomas Hozza |
3ddaff |
+ isc_buffer_free(&tmpbuf);
|
|
Tomas Hozza |
3ddaff |
+ return result;
|
|
Tomas Hozza |
3ddaff |
+ }
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
+ *dynbuffer = tmpbuf;
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
+ return (ISC_R_SUCCESS);
|
|
Tomas Hozza |
3ddaff |
+}
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
static void
|
|
Tomas Hozza |
3ddaff |
cancel_lookup(dig_lookup_t *lookup);
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
@@ -2416,8 +2446,10 @@ send_done(isc_task_t *_task, isc_event_t *event) {
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
for (b = ISC_LIST_HEAD(sevent->bufferlist);
|
|
Tomas Hozza |
3ddaff |
b != NULL;
|
|
Tomas Hozza |
3ddaff |
- b = ISC_LIST_HEAD(sevent->bufferlist))
|
|
Tomas Hozza |
3ddaff |
+ b = ISC_LIST_HEAD(sevent->bufferlist)) {
|
|
Tomas Hozza |
3ddaff |
ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
|
|
Tomas Hozza |
3ddaff |
+ isc_buffer_free(&b);
|
|
Tomas Hozza |
3ddaff |
+ }
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
query = event->ev_arg;
|
|
Tomas Hozza |
3ddaff |
query->waiting_senddone = ISC_FALSE;
|
|
Tomas Hozza |
3ddaff |
@@ -2617,6 +2649,7 @@ send_tcp_connect(dig_query_t *query) {
|
|
Tomas Hozza |
3ddaff |
static void
|
|
Tomas Hozza |
3ddaff |
send_udp(dig_query_t *query) {
|
|
Tomas Hozza |
3ddaff |
dig_lookup_t *l = NULL;
|
|
Tomas Hozza |
3ddaff |
+ isc_buffer_t *tmpbuf = NULL;
|
|
Tomas Hozza |
3ddaff |
isc_result_t result;
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
debug("send_udp(%p)", query);
|
|
Tomas Hozza |
3ddaff |
@@ -2663,8 +2696,14 @@ send_udp(dig_query_t *query) {
|
|
Tomas Hozza |
3ddaff |
recvcount++;
|
|
Tomas Hozza |
3ddaff |
debug("recvcount=%d", recvcount);
|
|
Tomas Hozza |
3ddaff |
}
|
|
Tomas Hozza |
3ddaff |
+ /*
|
|
Tomas Hozza |
3ddaff |
+ * Make a copy of the query send buffer so it is not reused
|
|
Tomas Hozza |
3ddaff |
+ * in multiple socket send events. The buffer is freed in send_done().
|
|
Tomas Hozza |
3ddaff |
+ */
|
|
Tomas Hozza |
3ddaff |
+ result = isc_buffer_cloneused(mctx, &query->sendbuf, &tmpbuf);
|
|
Tomas Hozza |
3ddaff |
+ check_result(result, "isc_buffer_cloneused");
|
|
Tomas Hozza |
3ddaff |
ISC_LIST_INIT(query->sendlist);
|
|
Tomas Hozza |
3ddaff |
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
|
|
Tomas Hozza |
3ddaff |
+ ISC_LIST_ENQUEUE(query->sendlist, tmpbuf, link);
|
|
Tomas Hozza |
3ddaff |
debug("sending a request");
|
|
Tomas Hozza |
3ddaff |
TIME_NOW(&query->time_sent);
|
|
Tomas Hozza |
3ddaff |
INSIST(query->sock != NULL);
|
|
Tomas Hozza |
3ddaff |
@@ -2838,6 +2877,7 @@ static void
|
|
Tomas Hozza |
3ddaff |
launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
|
|
Tomas Hozza |
3ddaff |
isc_result_t result;
|
|
Tomas Hozza |
3ddaff |
dig_lookup_t *l;
|
|
Tomas Hozza |
3ddaff |
+ isc_buffer_t *tmpbuf = NULL;
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
INSIST(!free_now);
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
@@ -2861,9 +2901,17 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
|
|
Tomas Hozza |
3ddaff |
isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
|
|
Tomas Hozza |
3ddaff |
ISC_LIST_INIT(query->sendlist);
|
|
Tomas Hozza |
3ddaff |
ISC_LINK_INIT(&query->slbuf, link);
|
|
Tomas Hozza |
3ddaff |
- ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
|
|
Tomas Hozza |
3ddaff |
- if (include_question)
|
|
Tomas Hozza |
3ddaff |
- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
|
|
Tomas Hozza |
3ddaff |
+
|
|
Tomas Hozza |
3ddaff |
+ /* need to clone send buffers as they are freed in send_done() */
|
|
Tomas Hozza |
3ddaff |
+ result = isc_buffer_cloneused(mctx, &query->slbuf, &tmpbuf);
|
|
Tomas Hozza |
3ddaff |
+ check_result(result, "isc_buffer_cloneused");
|
|
Tomas Hozza |
3ddaff |
+ ISC_LIST_ENQUEUE(query->sendlist, tmpbuf, link);
|
|
Tomas Hozza |
3ddaff |
+ if (include_question) {
|
|
Tomas Hozza |
3ddaff |
+ tmpbuf = NULL;
|
|
Tomas Hozza |
3ddaff |
+ result = isc_buffer_cloneused(mctx, &query->sendbuf, &tmpbuf);
|
|
Tomas Hozza |
3ddaff |
+ check_result(result, "isc_buffer_cloneused");
|
|
Tomas Hozza |
3ddaff |
+ ISC_LIST_ENQUEUE(query->sendlist, tmpbuf, link);
|
|
Tomas Hozza |
3ddaff |
+ }
|
|
Tomas Hozza |
3ddaff |
ISC_LINK_INIT(&query->lengthbuf, link);
|
|
Tomas Hozza |
3ddaff |
ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
|
|
Tomas Hozza |
3ddaff |
|
|
Tomas Hozza |
3ddaff |
--
|
|
Tomas Hozza |
3ddaff |
1.8.3.1
|
|
Tomas Hozza |
3ddaff |
|