From bea9188cd549883747bfc504dfaec13fbfad587a Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Fri, 25 May 2012 17:01:56 +0930 Subject: [PATCH] Fix another manifest leak Add manifest alloc/free debug logging to help, 'debug.manifests' option --- log.c | 1 + rhizome.h | 2 +- rhizome_bundle.c | 20 ++++++++++++++++---- rhizome_fetch.c | 19 ++++++++++++------- rhizome_packetformats.c | 11 ++++------- serval.h | 1 + 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/log.c b/log.c index aef53975..1654421f 100644 --- a/log.c +++ b/log.c @@ -148,6 +148,7 @@ long long debugFlagMask(const char *flagname) { else if (!strcasecmp(flagname,"monitorroutes")) return DEBUG_OVERLAYROUTEMONITOR; else if (!strcasecmp(flagname,"queues")) return DEBUG_QUEUES; else if (!strcasecmp(flagname,"broadcasts")) return DEBUG_BROADCASTS; + else if (!strcasecmp(flagname,"manifests")) return DEBUG_MANIFESTS; WARNF("Unsupported debug flag '%s'", flagname); return 0; } diff --git a/rhizome.h b/rhizome.h index 8573b730..8c7024ba 100644 --- a/rhizome.h +++ b/rhizome.h @@ -247,7 +247,7 @@ int rhizome_update_file_priority(char *fileid); int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found); int rhizome_manifest_to_bar(rhizome_manifest *m,unsigned char *bar); char nybltochar_upper(int n); -int rhizome_queue_manifest_import(rhizome_manifest *m,struct sockaddr_in *peerip); +int rhizome_queue_manifest_import(rhizome_manifest *m, struct sockaddr_in *peerip, int *manifest_kept); int rhizome_list_manifests(const char *service, const char *sender_sid, const char *recipient_sid, int limit, int offset); int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp); int rhizome_retrieve_file(const char *fileid, const char *filepath); diff --git a/rhizome_bundle.c b/rhizome_bundle.c index a165b7ed..31270885 100644 --- a/rhizome_bundle.c +++ b/rhizome_bundle.c @@ -288,6 +288,16 @@ const char *manifest_free_sourcefiles[MAX_RHIZOME_MANIFESTS]; const char *manifest_free_functions[MAX_RHIZOME_MANIFESTS]; int manifest_free_lines[MAX_RHIZOME_MANIFESTS]; +static void _log_manifest_trace(const char *filename, const char *funcname, int line, const char *operation) +{ + int count_free = 0; + int i; + for (i = 0; i != MAX_RHIZOME_MANIFESTS; ++i) + if (manifest_free[i]) + ++count_free; + logMessage(LOG_LEVEL_DEBUG, filename, line, funcname, "%s(): count_free = %d", operation, count_free); +} + rhizome_manifest *_rhizome_new_manifest(const char *filename, const char *funcname, int line) { if (manifest_first_free<0) { @@ -337,10 +347,10 @@ rhizome_manifest *_rhizome_new_manifest(const char *filename, const char *funcna manifest_free_lines[manifest_first_free]=-1; /* Work out where next free manifest record lives */ - for(;manifest_first_free=this_version) { /* this version is older than the one in the list, @@ -452,8 +451,12 @@ int rhizome_enqueue_suggestions() { if (rhizome_file_fetch_queue_count>=MAX_QUEUED_FILES) break; - rhizome_queue_manifest_import(candidates[i].manifest,&candidates[i].peer); - candidates[i].manifest=NULL; + int manifest_kept = 0; + rhizome_queue_manifest_import(candidates[i].manifest,&candidates[i].peer, &manifest_kept); + if (!manifest_kept) { + rhizome_manifest_free(candidates[i].manifest); + candidates[i].manifest = NULL; + } } if (i) { /* now shuffle up */ @@ -467,8 +470,9 @@ int rhizome_enqueue_suggestions() return 0; } -int rhizome_queue_manifest_import(rhizome_manifest *m, struct sockaddr_in *peerip) +int rhizome_queue_manifest_import(rhizome_manifest *m, struct sockaddr_in *peerip, int *manifest_kept) { + *manifest_kept = 0; int i; /* Do the quick rejection tests first, before the more expensive once, @@ -580,7 +584,8 @@ int rhizome_queue_manifest_import(rhizome_manifest *m, struct sockaddr_in *peeri rhizome_file_fetch_record *q=&file_fetch_queue[rhizome_file_fetch_queue_count]; - q->manifest=m; + q->manifest = m; + *manifest_kept = 1; q->socket=sock; strncpy(q->fileid, m->fileHexHash, RHIZOME_FILEHASH_STRLEN + 1); snprintf(q->request,1024,"GET /rhizome/file/%s HTTP/1.0\r\n\r\n", diff --git a/rhizome_packetformats.c b/rhizome_packetformats.c index 33eda1d7..f5f98aa4 100644 --- a/rhizome_packetformats.c +++ b/rhizome_packetformats.c @@ -402,8 +402,7 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now) rhizome_queue_ignore_manifest(m,(struct sockaddr_in*)f->recvaddr,60000); } if (m) rhizome_manifest_free(m); - m=NULL; - + m=NULL; if (importManifest) { /* Okay, so the manifest looks like it is potentially interesting to us, i.e., we don't already have it or a later version of it. @@ -412,29 +411,27 @@ int overlay_rhizome_saw_advertisements(int i,overlay_frame *f, long long now) WHY("Out of manifests"); else if (rhizome_read_manifest_file(m, (char *)&f->payload->bytes[ofs], manifest_length, RHIZOME_VERIFY) == -1) { WHY("Error importing manifest body"); - rhizome_manifest_free(m); + rhizome_manifest_free(m); m = NULL; } else if (m->errors) { if (debug&DEBUG_RHIZOME) DEBUGF("Verifying manifest %s revealed errors -- not storing.", manifest_id); rhizome_queue_ignore_manifest(m,(struct sockaddr_in*)f->recvaddr,60000); - rhizome_manifest_free(m); + rhizome_manifest_free(m); m = NULL; } else { if (debug&DEBUG_RHIZOME) DEBUGF("Verifying manifest %s revealed no errors -- will try to store.", manifest_id); /* Add manifest to import queue. We need to know originating IPv4 address so that we can transfer by HTTP. */ if (0) DEBUG("Suggesting fetching of a bundle"); - rhizome_suggest_queue_manifest_import(m,(struct sockaddr_in *)f->recvaddr); + rhizome_suggest_queue_manifest_import(m,(struct sockaddr_in *)f->recvaddr); } } - if (!manifest_length) { WHY("Infinite loop in packet decoding"); break; } ofs+=manifest_length; } - } return 0; diff --git a/serval.h b/serval.h index 70eb63f4..6c3ec11f 100755 --- a/serval.h +++ b/serval.h @@ -1073,6 +1073,7 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no #define DEBUG_RHIZOMESYNC (1 << 21) #define DEBUG_PACKETTX (1 << 22) #define DEBUG_PACKETCONSTRUCTION (1 << 23) +#define DEBUG_MANIFESTS (1 << 24) int serval_packetvisualise(FILE *f,char *message,unsigned char *packet,int plen);