Fix memory leak in TestingEnableCellStatsEvent

Only when we were actually flushing the cell stats to a controller
would we free them.  Thus, they could stay in RAM even after the
circuit was freed (eg if we didn't have any controllers).

Fixes bug 18673; bugfix on 0.2.5.1-alpha.
This commit is contained in:
Nick Mathewson 2016-03-28 10:37:22 -04:00
parent 65db5ae566
commit addd181721
4 changed files with 22 additions and 4 deletions

4
changes/bug18673 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes (memory leak):
- Fix a small memory leak that would occur when the
TestingEnableCellStatsEvent option was turned on. Fixes bug 18673;
bugfix on 0.2.5.2-alpha.

View File

@ -756,6 +756,18 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
return circ; return circ;
} }
/** Free all storage held in circ->testing_cell_stats */
void
circuit_clear_testing_cell_stats(circuit_t *circ)
{
if (!circ)
return;
SMARTLIST_FOREACH(circ->testing_cell_stats, testing_cell_stats_entry_t *,
ent, tor_free(ent));
smartlist_free(circ->testing_cell_stats);
circ->testing_cell_stats = NULL;
}
/** Deallocate space associated with circ. /** Deallocate space associated with circ.
*/ */
STATIC void STATIC void
@ -767,6 +779,8 @@ circuit_free(circuit_t *circ)
if (!circ) if (!circ)
return; return;
circuit_clear_testing_cell_stats(circ);
if (CIRCUIT_IS_ORIGIN(circ)) { if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
mem = ocirc; mem = ocirc;

View File

@ -71,6 +71,8 @@ void assert_circuit_ok(const circuit_t *c);
void circuit_free_all(void); void circuit_free_all(void);
void circuits_handle_oom(size_t current_allocation); void circuits_handle_oom(size_t current_allocation);
void circuit_clear_testing_cell_stats(circuit_t *circ);
void channel_note_destroy_pending(channel_t *chan, circid_t id); void channel_note_destroy_pending(channel_t *chan, circid_t id);
MOCK_DECL(void, channel_note_destroy_not_pending, MOCK_DECL(void, channel_note_destroy_not_pending,
(channel_t *chan, circid_t id)); (channel_t *chan, circid_t id));

View File

@ -4971,7 +4971,7 @@ sum_up_cell_stats_by_command(circuit_t *circ, cell_stats_t *cell_stats)
{ {
memset(cell_stats, 0, sizeof(cell_stats_t)); memset(cell_stats, 0, sizeof(cell_stats_t));
SMARTLIST_FOREACH_BEGIN(circ->testing_cell_stats, SMARTLIST_FOREACH_BEGIN(circ->testing_cell_stats,
testing_cell_stats_entry_t *, ent) { const testing_cell_stats_entry_t *, ent) {
tor_assert(ent->command <= CELL_COMMAND_MAX_); tor_assert(ent->command <= CELL_COMMAND_MAX_);
if (!ent->removed && !ent->exitward) { if (!ent->removed && !ent->exitward) {
cell_stats->added_cells_appward[ent->command] += 1; cell_stats->added_cells_appward[ent->command] += 1;
@ -4984,10 +4984,8 @@ sum_up_cell_stats_by_command(circuit_t *circ, cell_stats_t *cell_stats)
cell_stats->removed_cells_exitward[ent->command] += 1; cell_stats->removed_cells_exitward[ent->command] += 1;
cell_stats->total_time_exitward[ent->command] += ent->waiting_time * 10; cell_stats->total_time_exitward[ent->command] += ent->waiting_time * 10;
} }
tor_free(ent);
} SMARTLIST_FOREACH_END(ent); } SMARTLIST_FOREACH_END(ent);
smartlist_free(circ->testing_cell_stats); circuit_clear_testing_cell_stats(circ);
circ->testing_cell_stats = NULL;
} }
/** Helper: append a cell statistics string to <code>event_parts</code>, /** Helper: append a cell statistics string to <code>event_parts</code>,