aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-04-16 16:19:38 +0200
committerChristian Grothoff <christian@grothoff.org>2018-04-16 16:19:38 +0200
commita5335a605ba2a07936a6241b7d03793596c1255b (patch)
tree7bb8eefafeb84616facbf348bb0ecd75296094e1 /src
parentb983587ce81228c1337ebd0ebd492a29c0104cd2 (diff)
downloadgnunet-a5335a605ba2a07936a6241b7d03793596c1255b.tar.gz
gnunet-a5335a605ba2a07936a6241b7d03793596c1255b.zip
add DLL to plug leaks
Diffstat (limited to 'src')
-rw-r--r--src/namestore/gnunet-zoneimport.c160
1 files changed, 111 insertions, 49 deletions
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c
index 763687c59..8173ad9be 100644
--- a/src/namestore/gnunet-zoneimport.c
+++ b/src/namestore/gnunet-zoneimport.c
@@ -114,11 +114,21 @@ struct Record
114struct Request 114struct Request
115{ 115{
116 /** 116 /**
117 * Requests are kept in a heap. 117 * Requests are kept in a heap while waiting to be resolved.
118 */ 118 */
119 struct GNUNET_CONTAINER_HeapNode *hn; 119 struct GNUNET_CONTAINER_HeapNode *hn;
120 120
121 /** 121 /**
122 * Active requests are kept in a DLL.
123 */
124 struct Request *next;
125
126 /**
127 * Active requests are kept in a DLL.
128 */
129 struct Request *prev;
130
131 /**
122 * Head of records that should be published in GNS for 132 * Head of records that should be published in GNS for
123 * this hostname. 133 * this hostname.
124 */ 134 */
@@ -238,6 +248,16 @@ static unsigned int records;
238static struct GNUNET_CONTAINER_Heap *req_heap; 248static struct GNUNET_CONTAINER_Heap *req_heap;
239 249
240/** 250/**
251 * Active requests are kept in a DLL.
252 */
253static struct Request *req_head;
254
255/**
256 * Active requests are kept in a DLL.
257 */
258static struct Request *req_tail;
259
260/**
241 * Main task. 261 * Main task.
242 */ 262 */
243static struct GNUNET_SCHEDULER_Task *t; 263static struct GNUNET_SCHEDULER_Task *t;
@@ -322,6 +342,39 @@ for_all_records (const struct GNUNET_DNSPARSER_Packet *p,
322 342
323 343
324/** 344/**
345 * Free @a req and data structures reachable from it.
346 *
347 * @param req request to free
348 */
349static void
350free_request (struct Request *req)
351{
352 struct Record *rec;
353
354 while (NULL != (rec = req->rec_head))
355 {
356 GNUNET_CONTAINER_DLL_remove (req->rec_head,
357 req->rec_tail,
358 rec);
359 GNUNET_free (rec);
360 }
361 GNUNET_free (req->hostname);
362 GNUNET_free (req->label);
363 GNUNET_free (req->raw);
364 GNUNET_free (req);
365}
366
367
368/**
369 * Process as many requests as possible from the queue.
370 *
371 * @param cls NULL
372 */
373static void
374process_queue (void *cls);
375
376
377/**
325 * Insert @a req into DLL sorted by next fetch time. 378 * Insert @a req into DLL sorted by next fetch time.
326 * 379 *
327 * @param req request to insert into #req_heap 380 * @param req request to insert into #req_heap
@@ -332,6 +385,14 @@ insert_sorted (struct Request *req)
332 req->hn = GNUNET_CONTAINER_heap_insert (req_heap, 385 req->hn = GNUNET_CONTAINER_heap_insert (req_heap,
333 req, 386 req,
334 req->expires.abs_value_us); 387 req->expires.abs_value_us);
388 if (req == GNUNET_CONTAINER_heap_peek (req_heap))
389 {
390 if (NULL != t)
391 GNUNET_SCHEDULER_cancel (t);
392 t = GNUNET_SCHEDULER_add_at (req->expires,
393 &process_queue,
394 NULL);
395 }
335} 396}
336 397
337 398
@@ -745,25 +806,21 @@ process_result (void *cls,
745 unsigned int rd_count; 806 unsigned int rd_count;
746 807
747 (void) rs; 808 (void) rs;
809 GNUNET_assert (NULL == req->hn);
748 if (NULL == dns) 810 if (NULL == dns)
749 { 811 {
750 /* stub gave up */ 812 /* stub gave up */
813 GNUNET_CONTAINER_DLL_remove (req_head,
814 req_tail,
815 req);
751 pending--; 816 pending--;
752 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
753 "Stub gave up on DNS reply for `%s'\n", 818 "Stub gave up on DNS reply for `%s'\n",
754 req->hostname); 819 req->hostname);
755 if (NULL != req->hn)
756 {
757 GNUNET_break (0); /* should not be possible */
758 GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_node (req->hn));
759 req->hn = NULL;
760 }
761 if (req->issue_num > MAX_RETRIES) 820 if (req->issue_num > MAX_RETRIES)
762 { 821 {
763 failures++; 822 failures++;
764 GNUNET_free (req->hostname); 823 free_request (req);
765 GNUNET_free (req->raw);
766 GNUNET_free (req);
767 return; 824 return;
768 } 825 }
769 req->rs = NULL; 826 req->rs = NULL;
@@ -772,15 +829,12 @@ process_result (void *cls,
772 } 829 }
773 if (req->id != dns->id) 830 if (req->id != dns->id)
774 return; 831 return;
832 GNUNET_CONTAINER_DLL_remove (req_head,
833 req_tail,
834 req);
775 pending--; 835 pending--;
776 GNUNET_DNSSTUB_resolve_cancel (req->rs); 836 GNUNET_DNSSTUB_resolve_cancel (req->rs);
777 req->rs = NULL; 837 req->rs = NULL;
778 if (NULL != req->hn)
779 {
780 GNUNET_break (0); /* should not be possible */
781 GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_node (req->hn));
782 req->hn = NULL;
783 }
784 p = GNUNET_DNSPARSER_parse ((const char *) dns, 838 p = GNUNET_DNSPARSER_parse ((const char *) dns,
785 dns_len); 839 dns_len);
786 if (NULL == p) 840 if (NULL == p)
@@ -891,11 +945,17 @@ submit_req (struct Request *req)
891 struct GNUNET_TIME_Absolute now; 945 struct GNUNET_TIME_Absolute now;
892 946
893 if (NULL != req->rs) 947 if (NULL != req->rs)
948 {
949 GNUNET_break (0);
894 return GNUNET_NO; /* already submitted */ 950 return GNUNET_NO; /* already submitted */
951 }
895 now = GNUNET_TIME_absolute_get (); 952 now = GNUNET_TIME_absolute_get ();
896 if ( (now.abs_value_us - last_request.abs_value_us < TIME_THRESH) || 953 if ( (now.abs_value_us - last_request.abs_value_us < TIME_THRESH) ||
897 (pending >= THRESH) ) 954 (pending >= THRESH) )
898 return GNUNET_SYSERR; 955 return GNUNET_SYSERR;
956 GNUNET_CONTAINER_DLL_insert (req_head,
957 req_tail,
958 req);
899 GNUNET_assert (NULL == req->rs); 959 GNUNET_assert (NULL == req->rs);
900 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 960 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
901 "Requesting resolution for `%s'\n", 961 "Requesting resolution for `%s'\n",
@@ -947,48 +1007,47 @@ process_queue (void *cls)
947 1007
948 (void) cls; 1008 (void) cls;
949 t = NULL; 1009 t = NULL;
950 do 1010 while (1)
951 { 1011 {
952 req = GNUNET_CONTAINER_heap_peek (req_heap); 1012 req = GNUNET_CONTAINER_heap_peek (req_heap);
953 if (NULL == req) 1013 if (NULL == req)
954 break; 1014 break;
955 if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) 1015 if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0)
956 break; 1016 break;
957 GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_root (req_heap)); 1017 if (GNUNET_OK != submit_req (req))
1018 break;
1019 GNUNET_assert (req ==
1020 GNUNET_CONTAINER_heap_remove_root (req_heap));
958 req->hn = NULL; 1021 req->hn = NULL;
959 } 1022 }
960 while (GNUNET_SYSERR != submit_req (req));
961 1023
962 req = GNUNET_CONTAINER_heap_peek (req_heap); 1024 req = GNUNET_CONTAINER_heap_peek (req_heap);
963 if (NULL != req) 1025 if (NULL == req)
1026 return;
1027 if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0)
964 { 1028 {
965 if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0) 1029 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
966 { 1030 "Waiting until %s for next record (`%s') to expire\n",
967 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1031 GNUNET_STRINGS_absolute_time_to_string (req->expires),
968 "Waiting until %s for next record (`%s') to expire\n", 1032 req->hostname);
969 GNUNET_STRINGS_absolute_time_to_string (req->expires), 1033 finish_transaction ();
970 req->hostname); 1034 if (NULL != t)
971 finish_transaction (); 1035 GNUNET_SCHEDULER_cancel (t);
972 t = GNUNET_SCHEDULER_add_at (req->expires, 1036 t = GNUNET_SCHEDULER_add_at (req->expires,
973 &process_queue, 1037 &process_queue,
974 NULL); 1038 NULL);
975 }
976 else
977 {
978 if (0 == cnt++ % TRANSACTION_SYNC_FREQ)
979 finish_transaction ();
980 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
981 "Throttling for 1ms\n");
982 t = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
983 &process_queue,
984 NULL);
985 }
986 } 1039 }
987 else 1040 else
988 { 1041 {
989 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1042 if (0 == cnt++ % TRANSACTION_SYNC_FREQ)
990 "No more pending requests, terminating\n"); 1043 finish_transaction ();
991 GNUNET_SCHEDULER_shutdown (); 1044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1045 "Throttling for 1ms\n");
1046 if (NULL != t)
1047 GNUNET_SCHEDULER_cancel (t);
1048 t = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
1049 &process_queue,
1050 NULL);
992 } 1051 }
993} 1052}
994 1053
@@ -1029,12 +1088,17 @@ do_shutdown (void *cls)
1029 GNUNET_DNSSTUB_stop (ctx); 1088 GNUNET_DNSSTUB_stop (ctx);
1030 ctx = NULL; 1089 ctx = NULL;
1031 } 1090 }
1091 while (NULL != (req = req_head))
1092 {
1093 GNUNET_CONTAINER_DLL_remove (req_head,
1094 req_tail,
1095 req);
1096 free_request (req);
1097 }
1032 while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap))) 1098 while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap)))
1033 { 1099 {
1034 req->hn = NULL; 1100 req->hn = NULL;
1035 GNUNET_free (req->hostname); 1101 free_request (req);
1036 GNUNET_free (req->label);
1037 GNUNET_free (req);
1038 } 1102 }
1039 if (NULL != req_heap) 1103 if (NULL != req_heap)
1040 { 1104 {
@@ -1234,8 +1298,6 @@ process_stdin (void *cls)
1234 hn[strlen(hn)-1] = '\0'; /* eat newline */ 1298 hn[strlen(hn)-1] = '\0'; /* eat newline */
1235 queue (hn); 1299 queue (hn);
1236 } 1300 }
1237 t = GNUNET_SCHEDULER_add_now (&process_queue,
1238 NULL);
1239} 1301}
1240 1302
1241 1303