appl_request_downstream_free gets called from 3 locations: - appl_request_upstream_free: called from appl_request_upstream_reply and cleans up after a request has been answered, whether all the downstream requests have been completed or not (when timed out) - appl_response: When a downstream reqeuest has been completed - appl_close: When a downstream backend has been closed.
appl_request_upstream_free is already done with the upstream request and appl_response already automatically starts the next iteration of missing varbinds. The problem arrises when appl_close is called (e.g. a backend disappears unexpected) while there are still pending downstream requests. In that case all references to the upstream request are lost and we have a memory leak. Diff below resets the pending varbinds to new and restarts the parsing procedure. OK? martijn@ Index: application.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/application.c,v retrieving revision 1.6 diff -u -p -r1.6 application.c --- application.c 30 Jun 2022 11:28:36 -0000 1.6 +++ application.c 22 Jul 2022 14:59:00 -0000 @@ -716,6 +716,7 @@ void appl_request_downstream_free(struct appl_request_downstream *dreq) { struct appl_varbind_internal *vb; + int retry = 0; if (dreq == NULL) return; @@ -723,9 +724,16 @@ appl_request_downstream_free(struct appl RB_REMOVE(appl_requests, &(dreq->ard_backend->ab_requests), dreq); evtimer_del(&(dreq->ard_timer)); - for (vb = dreq->ard_vblist; vb != NULL; vb = vb->avi_next) + for (vb = dreq->ard_vblist; vb != NULL; vb = vb->avi_next) { vb->avi_request_downstream = NULL; + if (vb->avi_state == APPL_VBSTATE_PENDING) { + vb->avi_state = APPL_VBSTATE_NEW; + retry = 1; + } + } + if (retry) + appl_request_upstream_resolve(dreq->ard_request); free(dreq); }