From 91ec6f7269bd7a5b73629f38e9779e84a0fb84f2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 15 Nov 2013 18:38:52 -0500 Subject: Have the OOM handler also count the age the data in a stream buffer --- src/or/buffers.c | 41 ++++++++++++++++++++++++++++ src/or/buffers.h | 3 +++ src/or/circuitlist.c | 75 +++++++++++++++++++++++++++++++++++++++++----------- src/or/or.h | 3 +++ src/or/relay.c | 1 + 5 files changed, 108 insertions(+), 15 deletions(-) diff --git a/src/or/buffers.c b/src/or/buffers.c index 9be0476f6..4b176a83e 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -68,6 +68,8 @@ typedef struct chunk_t { size_t datalen; /**< The number of bytes stored in this chunk */ size_t memlen; /**< The number of usable bytes of storage in mem. */ char *data; /**< A pointer to the first byte of data stored in mem. */ + uint32_t inserted_time; /**< Timestamp in truncated ms since epoch + * when this chunk was inserted. */ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in * this chunk. */ } chunk_t; @@ -139,6 +141,9 @@ static chunk_freelist_t freelists[] = { * could help with? */ static uint64_t n_freelist_miss = 0; +/** DOCDOC */ +static size_t total_bytes_allocated_in_chunks = 0; + static void assert_freelist_ok(chunk_freelist_t *fl); /** Return the freelist to hold chunks of size alloc, or NULL if @@ -172,6 +177,8 @@ chunk_free_unchecked(chunk_t *chunk) } else { if (freelist) ++freelist->n_free; + tor_assert(total_bytes_allocated_in_chunks >= alloc); + total_bytes_allocated_in_chunks -= alloc; tor_free(chunk); } } @@ -200,6 +207,7 @@ chunk_new_with_alloc_size(size_t alloc) else ++n_freelist_miss; ch = tor_malloc(alloc); + total_bytes_allocated_in_chunks += alloc; } ch->next = NULL; ch->datalen = 0; @@ -211,6 +219,10 @@ chunk_new_with_alloc_size(size_t alloc) static void chunk_free_unchecked(chunk_t *chunk) { + if (!chunk) + return; + tor_assert(total_bytes_allocated_in_chunks >= CHUNK_ALLOC_SIZE(chunk->memlen)); + total_bytes_allocated_in_chunks -= CHUNK_ALLOC_SIZE(chunk->memlen); tor_free(chunk); } static INLINE chunk_t * @@ -221,6 +233,7 @@ chunk_new_with_alloc_size(size_t alloc) ch->next = NULL; ch->datalen = 0; ch->memlen = CHUNK_SIZE_WITH_ALLOC(alloc); + total_bytes_allocated_in_chunks += alloc; ch->data = &ch->mem[0]; return ch; } @@ -237,6 +250,7 @@ chunk_grow(chunk_t *chunk, size_t sz) chunk = tor_realloc(chunk, CHUNK_ALLOC_SIZE(sz)); chunk->memlen = sz; chunk->data = chunk->mem + offset; + total_bytes_allocated_in_chunks += (sz - chunk->memlen); return chunk; } @@ -298,6 +312,8 @@ buf_shrink_freelists(int free_all) *chp = NULL; while (chunk) { chunk_t *next = chunk->next; + tor_assert(total_bytes_allocated_in_chunks >= CHUNK_ALLOC_SIZE(chunk->memlen)); + total_bytes_allocated_in_chunks -= CHUNK_ALLOC_SIZE(chunk->memlen); tor_free(chunk); chunk = next; --n_to_free; @@ -599,6 +615,7 @@ static chunk_t * buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped) { chunk_t *chunk; + struct timeval now; if (CHUNK_ALLOC_SIZE(capacity) < buf->default_chunk_size) { chunk = chunk_new_with_alloc_size(buf->default_chunk_size); } else if (capped && CHUNK_ALLOC_SIZE(capacity) > MAX_CHUNK_ALLOC) { @@ -606,6 +623,10 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped) } else { chunk = chunk_new_with_alloc_size(preferred_chunk_size(capacity)); } + + tor_gettimeofday_cached(&now); + chunk->inserted_time = (uint32_t)tv_to_msec(&now); + if (buf->tail) { tor_assert(buf->head); buf->tail->next = chunk; @@ -618,6 +639,26 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped) return chunk; } +/** Return the age of the oldest chunk in the buffer buf, in + * milliseconds. Requires the current time, in truncated milliseconds since + * the epoch, as its input now. + */ +uint32_t +buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now) +{ + if (buf->head) { + return now - buf->head->inserted_time; + } else { + return 0; + } +} + +size_t +buf_get_total_allocation(void) +{ + return total_bytes_allocated_in_chunks; +} + /** Read up to at_most bytes from the socket fd into * chunk (which must be on buf). If we get an EOF, set * *reached_eof to 1. Return -1 on error, 0 on eof or blocking, diff --git a/src/or/buffers.h b/src/or/buffers.h index a5886adc7..677d68d83 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -25,6 +25,9 @@ size_t buf_datalen(const buf_t *buf); size_t buf_allocation(const buf_t *buf); size_t buf_slack(const buf_t *buf); +uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now); +size_t buf_get_total_allocation(void); + int read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof, int *socket_error); int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 6250c11d2..27fe5abbe 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1409,20 +1409,63 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) return age; } -/** Temporary variable for circuits_compare_by_oldest_queued_cell_ This is a - * kludge to work around the fact that qsort doesn't provide a way for - * comparison functions to take an extra argument. */ -static uint32_t circcomp_now_tmp; +/** DOCDOC*/ +static uint32_t +circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) +{ + uint32_t age = 0, age2; + for (; stream; stream = stream->next_stream) { + const connection_t *conn = TO_CONN(stream); + if (conn->outbuf) { + age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now); + if (age2 > age) + age = age2; + } + if (conn->inbuf) { + age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now); + if (age2 > age) + age = age2; + } + } + + return age; +} + +/** DOCDOC + */ +static uint32_t +circuit_max_queued_data_age(const circuit_t *c, uint32_t now) +{ + if (CIRCUIT_IS_ORIGIN(c)) { + return circuit_get_streams_max_data_age( + TO_ORIGIN_CIRCUIT((circuit_t*)c)->p_streams, now); + } else { + return circuit_get_streams_max_data_age( + TO_OR_CIRCUIT((circuit_t*)c)->n_streams, now); + } +} + +/** DATA */ +static uint32_t +circuit_max_queued_item_age(const circuit_t *c, uint32_t now) +{ + uint32_t cell_age = circuit_max_queued_cell_age(c, now); + uint32_t data_age = circuit_max_queued_data_age(c, now); + if (cell_age > data_age) + return cell_age; + else + return data_age; +} -/** Helper to sort a list of circuit_t by age of oldest cell, in descending - * order. Requires that circcomp_now_tmp is set correctly. */ +/** Helper to sort a list of circuit_t by age of oldest item, in descending + * order. */ static int -circuits_compare_by_oldest_queued_cell_(const void **a_, const void **b_) +circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) { const circuit_t *a = *a_; const circuit_t *b = *b_; - uint32_t age_a = circuit_max_queued_cell_age(a, circcomp_now_tmp); - uint32_t age_b = circuit_max_queued_cell_age(b, circcomp_now_tmp); + uint32_t age_a = a->age_tmp; + uint32_t age_b = b->age_tmp; if (age_a < age_b) return 1; @@ -1446,6 +1489,7 @@ circuits_handle_oom(size_t current_allocation) size_t n_cells_removed=0, n_cells_to_remove; int n_circuits_killed=0; struct timeval now; + uint32_t now_ms; log_notice(LD_GENERAL, "We're low on memory. Killing circuits with " "over-long queues. (This behavior is controlled by " "MaxMemInCellQueues.)"); @@ -1460,18 +1504,19 @@ circuits_handle_oom(size_t current_allocation) n_cells_to_remove = CEIL_DIV(mem_to_recover, packed_cell_mem_cost()); } + tor_gettimeofday_cached(&now); + now_ms = (uint32_t)tv_to_msec(&now); + /* This algorithm itself assumes that you've got enough memory slack * to actually run it. */ - for (circ = global_circuitlist; circ; circ = circ->next) + for (circ = global_circuitlist; circ; circ = circ->next) { + circ->age_tmp = circuit_max_queued_item_age(circ, now_ms); smartlist_add(circlist, circ); - - /* Set circcomp_now_tmp so that the sort can work. */ - tor_gettimeofday_cached(&now); - circcomp_now_tmp = (uint32_t)tv_to_msec(&now); + } /* This is O(n log n); there are faster algorithms we could use instead. * Let's hope this doesn't happen enough to be in the critical path. */ - smartlist_sort(circlist, circuits_compare_by_oldest_queued_cell_); + smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_); /* Okay, now the worst circuits are at the front of the list. Let's mark * them, and reclaim their storage aggressively. */ diff --git a/src/or/or.h b/src/or/or.h index 462239190..0dd47d03b 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2564,6 +2564,9 @@ typedef struct circuit_t { * more. */ int deliver_window; + /** Temporary field used during circuits_handle_oom. */ + uint32_t age_tmp; + /** For storage while n_conn is pending * (state CIRCUIT_STATE_OR_WAIT). When defined, it is always * length ONIONSKIN_CHALLENGE_LEN. */ diff --git a/src/or/relay.c b/src/or/relay.c index a193ad843..042fc18d1 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1998,6 +1998,7 @@ static int cell_queues_check_size(void) { size_t alloc = total_cells_allocated * packed_cell_mem_cost(); + alloc += buf_get_total_allocation(); if (alloc >= get_options()->MaxMemInCellQueues) { circuits_handle_oom(alloc); return 1; -- cgit v1.2.3 From eabcab2b7caab75ba8607c7dac225e4533998e80 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 20 Nov 2013 11:56:35 -0500 Subject: Count freed buffer bytes from buffers when oom-killing circuits. Also, aggressively clear the buffers to try to make their bytes go away fast rather than waiting for the close-marked-connection code to get 'em. --- src/or/buffers.c | 2 +- src/or/circuitlist.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/or/buffers.c b/src/or/buffers.c index 4b176a83e..71b61b189 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -547,7 +547,7 @@ buf_allocation(const buf_t *buf) size_t total = 0; const chunk_t *chunk; for (chunk = buf->head; chunk; chunk = chunk->next) { - total += chunk->memlen; + total += CHUNK_ALLOC_SIZE(chunk->memlen); } return total; } diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 27fe5abbe..c7dfe36cf 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1373,6 +1373,36 @@ marked_circuit_free_cells(circuit_t *circ) cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_conn_cells); } +/** DOCDOC */ +static size_t +marked_circuit_streams_free_bytes(edge_connection_t *stream) +{ + size_t result = 0; + for ( ; stream; stream = stream->next_stream) { + connection_t *conn = TO_CONN(stream); + if (conn->inbuf) { + result += buf_allocation(conn->inbuf); + buf_clear(conn->inbuf); + } + if (conn->outbuf) { + result += buf_allocation(conn->outbuf); + buf_clear(conn->outbuf); + } + } + return result; +} + +/** DOCDOC */ +static size_t +marked_circuit_free_stream_bytes(circuit_t *c) +{ + if (CIRCUIT_IS_ORIGIN(c)) { + return marked_circuit_streams_free_bytes(TO_ORIGIN_CIRCUIT(c)->p_streams); + } else { + return marked_circuit_streams_free_bytes(TO_OR_CIRCUIT(c)->n_streams); + } +} + /** Return the number of cells used by the circuit c's cell queues. */ static size_t n_cells_in_circ_queues(const circuit_t *c) @@ -1486,7 +1516,8 @@ circuits_handle_oom(size_t current_allocation) /* Let's hope there's enough slack space for this allocation here... */ smartlist_t *circlist = smartlist_new(); circuit_t *circ; - size_t n_cells_removed=0, n_cells_to_remove; + size_t mem_to_recover; + size_t mem_recovered=0; int n_circuits_killed=0; struct timeval now; uint32_t now_ms; @@ -1497,11 +1528,9 @@ circuits_handle_oom(size_t current_allocation) { size_t mem_target = (size_t)(get_options()->MaxMemInCellQueues * FRACTION_OF_CELLS_TO_RETAIN_ON_OOM); - size_t mem_to_recover; if (current_allocation <= mem_target) return; mem_to_recover = current_allocation - mem_target; - n_cells_to_remove = CEIL_DIV(mem_to_recover, packed_cell_mem_cost()); } tor_gettimeofday_cached(&now); @@ -1522,21 +1551,26 @@ circuits_handle_oom(size_t current_allocation) * them, and reclaim their storage aggressively. */ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { size_t n = n_cells_in_circ_queues(circ); + size_t freed; if (! circ->marked_for_close) { circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); } marked_circuit_free_cells(circ); + freed = marked_circuit_free_stream_bytes(circ); ++n_circuits_killed; - n_cells_removed += n; - if (n_cells_removed >= n_cells_to_remove) + + mem_recovered += n * packed_cell_mem_cost(); + mem_recovered += freed; + + if (mem_recovered >= mem_to_recover) break; } SMARTLIST_FOREACH_END(circ); clean_cell_pool(); /* In case this helps. */ log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits.", - U64_PRINTF_ARG(n_cells_removed * packed_cell_mem_cost()), + U64_PRINTF_ARG(mem_recovered), n_circuits_killed); smartlist_free(circlist); -- cgit v1.2.3 From a406f6d0f05f812ced4bfc048f30bc8692be7e93 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 20 Nov 2013 12:01:21 -0500 Subject: doxygen comments for 10169 code --- src/or/circuitlist.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index c7dfe36cf..3237b1e39 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1373,7 +1373,8 @@ marked_circuit_free_cells(circuit_t *circ) cell_queue_clear(& TO_OR_CIRCUIT(circ)->p_conn_cells); } -/** DOCDOC */ +/** Aggressively free buffer contents on all the buffers of all streams in the + * list starting at stream. Return the number of bytes recovered. */ static size_t marked_circuit_streams_free_bytes(edge_connection_t *stream) { @@ -1392,7 +1393,8 @@ marked_circuit_streams_free_bytes(edge_connection_t *stream) return result; } -/** DOCDOC */ +/** Aggressively free buffer contents on all the buffers of all streams on + * circuit c. Return the number of bytes recovered. */ static size_t marked_circuit_free_stream_bytes(circuit_t *c) { @@ -1439,7 +1441,9 @@ circuit_max_queued_cell_age(const circuit_t *c, uint32_t now) return age; } -/** DOCDOC*/ +/** Return the age in milliseconds of the oldest buffer chunk on any stream in + * the linked list stream, where age is taken in milliseconds before + * the time now (in truncated milliseconds since the epoch). */ static uint32_t circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) { @@ -1461,8 +1465,9 @@ circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now) return age; } -/** DOCDOC - */ +/** Return the age in milliseconds of the oldest buffer chunk on any stream + * attached to the circuit c, where age is taken in milliseconds before + * the time now (in truncated milliseconds since the epoch). */ static uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now) { @@ -1475,7 +1480,9 @@ circuit_max_queued_data_age(const circuit_t *c, uint32_t now) } } -/** DATA */ +/** Return the age of the oldest cell or stream buffer chunk on the circuit + * c, where age is taken in milliseconds before the time now (in + * truncated milliseconds since the epoch). */ static uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now) { -- cgit v1.2.3 From 03ff21b018c8d0b005d2a60c3ba2bf08d6cb00bb Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 20 Nov 2013 12:08:03 -0500 Subject: Changess file for #10169 --- changes/bug10169 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/bug10169 diff --git a/changes/bug10169 b/changes/bug10169 new file mode 100644 index 000000000..979c4e428 --- /dev/null +++ b/changes/bug10169 @@ -0,0 +1,4 @@ + o Major features: + - Also consider stream buffer sizes when calculating OOM + conditions. Rename MaxMemInCellQueues to MaxMemInQueues. Fixes + bug 10169. -- cgit v1.2.3 From e572ec856dff263d7f43ec6d42fe3fc3b7557f73 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 20 Nov 2013 12:08:14 -0500 Subject: Rename MaxMemInCellQueues to MaxMemInQueues --- doc/tor.1.txt | 10 +++++----- src/or/circuitlist.c | 10 +++++----- src/or/config.c | 9 +++++---- src/or/or.h | 5 ++--- src/or/relay.c | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 1f3afef2a..01f0be75e 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1475,13 +1475,13 @@ is non-zero): localhost, RFC1918 addresses, and so on. This can create security issues; you should probably leave it off. (Default: 0) -**MaxMemInCellQueues** __N__ **bytes**|**KB**|**MB**|**GB**:: +**MaxMemInQueues** __N__ **bytes**|**KB**|**MB**|**GB**:: This option configures a threshold above which Tor will assume that it - needs to stop queueing cells because it's about to run out of memory. - If it hits this threshold, it will begin killing circuits until it - has recovered at least 10% of this memory. Do not set this option too + needs to stop queueing or buffering data because it's about to run out of + memory. If it hits this threshold, it will begin killing circuits until + it has recovered at least 10% of this memory. Do not set this option too low, or your relay may be unreliable under load. This option only - effects circuit queues, so the actual process size will be larger than + affects some queues, so the actual process size will be larger than this. (Default: 8GB) DIRECTORY SERVER OPTIONS diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 3237b1e39..2e135416c 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1512,11 +1512,11 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_) return -1; } -#define FRACTION_OF_CELLS_TO_RETAIN_ON_OOM 0.90 +#define FRACTION_OF_DATA_TO_RETAIN_ON_OOM 0.90 /** We're out of memory for cells, having allocated current_allocation * bytes' worth. Kill the 'worst' circuits until we're under - * FRACTION_OF_CIRCS_TO_RETAIN_ON_OOM of our maximum usage. */ + * FRACTION_OF_DATA_TO_RETAIN_ON_OOM of our maximum usage. */ void circuits_handle_oom(size_t current_allocation) { @@ -1530,11 +1530,11 @@ circuits_handle_oom(size_t current_allocation) uint32_t now_ms; log_notice(LD_GENERAL, "We're low on memory. Killing circuits with " "over-long queues. (This behavior is controlled by " - "MaxMemInCellQueues.)"); + "MaxMemInQueues.)"); { - size_t mem_target = (size_t)(get_options()->MaxMemInCellQueues * - FRACTION_OF_CELLS_TO_RETAIN_ON_OOM); + size_t mem_target = (size_t)(get_options()->MaxMemInQueues * + FRACTION_OF_DATA_TO_RETAIN_ON_OOM); if (current_allocation <= mem_target) return; mem_to_recover = current_allocation - mem_target; diff --git a/src/or/config.c b/src/or/config.c index d5c568947..0accb65e5 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -115,6 +115,7 @@ static config_abbrev_t _option_abbrevs[] = { { "BandwidthBurstBytes", "BandwidthBurst", 0, 0}, { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0}, { "MaxConn", "ConnLimit", 0, 1}, + { "MaxMemInCellQueues", "MaxMemInQueues", 0, 0}, { "ORBindAddress", "ORListenAddress", 0, 0}, { "DirBindAddress", "DirListenAddress", 0, 0}, { "SocksBindAddress", "SocksListenAddress", 0, 0}, @@ -343,7 +344,7 @@ static config_var_t _option_vars[] = { V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"), V(MaxCircuitDirtiness, INTERVAL, "10 minutes"), V(MaxClientCircuitsPending, UINT, "32"), - V(MaxMemInCellQueues, MEMUNIT, "8 GB"), + V(MaxMemInQueues, MEMUNIT, "8 GB"), V(MaxOnionsPending, UINT, "100"), OBSOLETE("MonthlyAccountingStart"), V(MyFamily, STRING, NULL), @@ -3669,10 +3670,10 @@ options_validate(or_options_t *old_options, or_options_t *options, log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. " "EntryNodes will be ignored."); - if (options->MaxMemInCellQueues < (500 << 20)) { - log_warn(LD_CONFIG, "MaxMemInCellQueues must be at least 500 MB for now. " + if (options->MaxMemInQueues < (500 << 20)) { + log_warn(LD_CONFIG, "MaxMemInQueues must be at least 500 MB for now. " "Ideally, have it as large as you can afford."); - options->MaxMemInCellQueues = (500 << 20); + options->MaxMemInQueues = (500 << 20); } options->_AllowInvalid = 0; diff --git a/src/or/or.h b/src/or/or.h index 0dd47d03b..c323783ee 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3075,9 +3075,8 @@ typedef struct { config_line_t *DirPort_lines; config_line_t *DNSPort_lines; /**< Ports to listen on for DNS requests. */ - uint64_t MaxMemInCellQueues; /**< If we have more memory than this allocated - * for circuit cell queues, run the OOM handler - */ + uint64_t MaxMemInQueues; /**< If we have more memory than this allocated + * for queues and buffers, run the OOM handler */ /** @name port booleans * diff --git a/src/or/relay.c b/src/or/relay.c index 042fc18d1..e6d0f50ac 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -1999,7 +1999,7 @@ cell_queues_check_size(void) { size_t alloc = total_cells_allocated * packed_cell_mem_cost(); alloc += buf_get_total_allocation(); - if (alloc >= get_options()->MaxMemInCellQueues) { + if (alloc >= get_options()->MaxMemInQueues) { circuits_handle_oom(alloc); return 1; } -- cgit v1.2.3 From 647248729fa65f0e51d062e2af8f4e8b38592bf5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 20 Nov 2013 12:12:47 -0500 Subject: Drop the MaxMemInQueues lower limit down to 256 MB. on #9686, gmorehose reports that the 500 MB lower limit is too high for raspberry pi users. --- changes/bug9686 | 3 +++ src/or/config.c | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 changes/bug9686 diff --git a/changes/bug9686 b/changes/bug9686 new file mode 100644 index 000000000..82a8f4447 --- /dev/null +++ b/changes/bug9686 @@ -0,0 +1,3 @@ + o Minor changes: + - Decrease the lower limit of MaxMemInQueues to 256 MBytes, to + appease raspberry pi users. Fixes bug 9686. \ No newline at end of file diff --git a/src/or/config.c b/src/or/config.c index 0accb65e5..01e62d6d4 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3670,10 +3670,10 @@ options_validate(or_options_t *old_options, or_options_t *options, log_warn(LD_CONFIG, "EntryNodes is set, but UseEntryGuards is disabled. " "EntryNodes will be ignored."); - if (options->MaxMemInQueues < (500 << 20)) { - log_warn(LD_CONFIG, "MaxMemInQueues must be at least 500 MB for now. " + if (options->MaxMemInQueues < (256 << 20)) { + log_warn(LD_CONFIG, "MaxMemInQueues must be at least 256 MB for now. " "Ideally, have it as large as you can afford."); - options->MaxMemInQueues = (500 << 20); + options->MaxMemInQueues = (256 << 20); } options->_AllowInvalid = 0; -- cgit v1.2.3