diff --git a/doc/spec/path-spec.txt b/doc/spec/path-spec.txt
index ae5ab3e3dd30ada66129342a68b50875e1bf22be..2beeedeace3a108c33360491908d349fbf7b3c0c 100644
--- a/doc/spec/path-spec.txt
+++ b/doc/spec/path-spec.txt
@@ -382,6 +382,12 @@ of their choices.
    construction. If these parameters are not present in the consensus,
    the listed default values should be used instead.
 
+      cbtdisabled
+        Default: 0
+        Effect: If non-zero, all CircuitBuildTime learning code should be
+                disabled and history should be discarded. For use in
+                emergency situations only.
+
       cbtrecentcount
         Default: 20
         Effect: This is the number of circuit build times to keep track of
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 2ae5005d8c553c3af44f9bb7abdd6fb6be0d81dc..e6bce02e3b2d4ac8b9a0a9bd68dda00be7fa1ad1 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -419,9 +419,16 @@ The following options are useful only for clients (that is, if
     fingerprint to look up the bridge descriptor at the bridge authority, if
     it's provided and if UpdateBridgesFromAuthority is set too.
 
+**LearnCircuitBuildTimeout** **0**|**1**::
+    If 0, CircuitBuildTimeout adaptive learning is disabled. (Default: 1)
+
 **CircuitBuildTimeout** __NUM__::
+
     Try for at most NUM seconds when building circuits. If the circuit isn't
-    open in that time, give up on it. (Default: 1 minute.)
+    open in that time, give up on it. If LearnCircuitBuildTimeout is 1, this
+    value serves as the initial value to use before a timeout is learned. If
+    LearnCircuitBuildTimeout is 0, this value is the only value used.
+    (Default: 60 seconds.)
 
 **CircuitIdleTimeout** __NUM__::
     If we have kept a clean (never used) circuit around for NUM seconds, then
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 3600ce7c4d113d52ecff7890b6b4a9d339c56c0f..4f79d32444c014a8edb6423cd836bad9d155b345 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -81,6 +81,28 @@ static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
 
 static void entry_guards_changed(void);
 
+static int
+circuit_build_times_disabled(void)
+{
+  int consensus_disabled = networkstatus_get_param(NULL, "cbtdisabled",
+                                                   0);
+  int config_disabled = !get_options()->LearnCircuitBuildTimeout;
+  int dirauth_disabled = get_options()->AuthoritativeDir;
+  int state_disabled = (get_or_state()->LastWritten == -1);
+
+  if (consensus_disabled || config_disabled || dirauth_disabled ||
+         state_disabled) {
+    log_info(LD_CIRC,
+             "CircuitBuildTime learning is disabled. "
+             "Consensus=%d, Config=%d, AuthDir=%d, StateFile=%d",
+             consensus_disabled, config_disabled, dirauth_disabled,
+             state_disabled);
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
 static int32_t
 circuit_build_times_max_timeouts(void)
 {
@@ -531,11 +553,16 @@ circuit_build_times_parse_state(circuit_build_times_t *cbt,
   uint32_t loaded_cnt = 0, N = 0;
   config_line_t *line;
   int i;
-  build_time_t *loaded_times = tor_malloc(sizeof(build_time_t)
-                                          * state->TotalBuildTimes);
+  build_time_t *loaded_times;
   circuit_build_times_init(cbt);
   *msg = NULL;
 
+  if (circuit_build_times_disabled()) {
+    return 0;
+  }
+
+  loaded_times = tor_malloc(sizeof(build_time_t)*state->TotalBuildTimes);
+
   for (line = state->BuildtimeHistogram; line; line = line->next) {
     smartlist_t *args = smartlist_create();
     smartlist_split_string(args, line->value, " ",
@@ -1020,6 +1047,11 @@ circuit_build_times_add_timeout(circuit_build_times_t *cbt,
                                 int did_onehop,
                                 time_t start_time)
 {
+  if (circuit_build_times_disabled()) {
+    cbt->timeout_ms = circuit_build_times_get_initial_timeout();
+    return 0;
+  }
+
   circuit_build_times_network_timeout(cbt, did_onehop, start_time);
 
   /* Only count timeouts if network is live.. */
@@ -1769,7 +1801,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
         if (timediff < 0 || timediff > 2*circ_times.timeout_ms+1000) {
           log_notice(LD_CIRC, "Strange value for circuit build time: %ld. "
                               "Assuming clock jump.", timediff);
-        } else {
+        } else if (!circuit_build_times_disabled()) {
           circuit_build_times_add_time(&circ_times, (build_time_t)timediff);
           circuit_build_times_network_circ_success(&circ_times);
           circuit_build_times_set_timeout(&circ_times);
diff --git a/src/or/config.c b/src/or/config.c
index 5d07cd7343aaf63e0b54700648fcc334bcfd528d..77ef45ec42afe4692991e249c6754ea663c3e1bc 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -167,6 +167,7 @@ static config_var_t _option_vars[] = {
   V(BridgeRecordUsageByCountry,  BOOL,     "1"),
   V(BridgeRelay,                 BOOL,     "0"),
   V(CellStatistics,              BOOL,     "0"),
+  V(LearnCircuitBuildTimeout,    BOOL,     "1"),
   V(CircuitBuildTimeout,         INTERVAL, "0"),
   V(CircuitIdleTimeout,          INTERVAL, "1 hour"),
   V(CircuitStreamTimeout,        INTERVAL, "0"),
@@ -4982,7 +4983,6 @@ or_state_save(time_t now)
   if (accounting_is_enabled(get_options()))
     accounting_run_housekeeping(now);
 
-  global_state->LastWritten = time(NULL);
   tor_free(global_state->TorVersion);
   tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
 
@@ -4997,10 +4997,13 @@ or_state_save(time_t now)
   fname = get_datadir_fname("state");
   if (write_str_to_file(fname, contents, 0)<0) {
     log_warn(LD_FS, "Unable to write state to file \"%s\"", fname);
+    global_state->LastWritten = -1;
     tor_free(fname);
     tor_free(contents);
     return -1;
   }
+
+  global_state->LastWritten = time(NULL);
   log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
   tor_free(fname);
   tor_free(contents);
diff --git a/src/or/or.h b/src/or/or.h
index f31847408e0a10f9b13921646717a8cc0f1d1305..36c45e2db03c02b4f27beb6fb0e70dce7dd0d7e1 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2496,9 +2496,12 @@ typedef struct {
                         * connections alive? */
   int SocksTimeout; /**< How long do we let a socks connection wait
                      * unattached before we fail it? */
-  int CircuitBuildTimeout; /**< If non-zero, cull non-open circuits that
-                            * were born at least this many seconds ago. If
-                            * zero, use the internal adaptive algorithm. */
+  int LearnCircuitBuildTimeout; /**< If non-zero, we attempt to learn a value
+                                 * for CircuitBuildTimeout based on timeout
+                                 * history */
+  int CircuitBuildTimeout; /**< Cull non-open circuits that were born at
+                            * least this many seconds ago. Used until
+                            * adaptive algorithm learns a new value. */
   int CircuitIdleTimeout; /**< Cull open clean circuits that were born
                            * at least this many seconds ago. */
   int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits