Browse Source

Merge branch 'bug7350' of ssh://git-rw.torproject.org/user/andrea/tor

Andrea Shepard 11 years ago
parent
commit
9f3f5372b8
3 changed files with 39 additions and 12 deletions
  1. 5 0
      changes/bug7350
  2. 22 10
      src/or/channel.c
  3. 12 2
      src/or/circuitlist.c

+ 5 - 0
changes/bug7350

@@ -0,0 +1,5 @@
+  o Minor bugfixes:
+    - Avoid a possible assert that can occur when channel_send_destroy() is
+      called on a channel in CHANNEL_STATE_CLOSING, CHANNEL_STATE_CLOSED
+      or CHANNEL_STATE_ERROR when the Tor process is resumed after being
+      blocked for a long interval.  Fixes bug 7350.

+ 22 - 10
src/or/channel.c

@@ -2585,17 +2585,29 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
 
   tor_assert(chan);
 
-  memset(&cell, 0, sizeof(cell_t));
-  cell.circ_id = circ_id;
-  cell.command = CELL_DESTROY;
-  cell.payload[0] = (uint8_t) reason;
-  log_debug(LD_OR,
-            "Sending destroy (circID %d) on channel %p "
-            "(global ID " U64_FORMAT ")",
-            circ_id, chan,
-            U64_PRINTF_ARG(chan->global_identifier));
+  /* Check to make sure we can send on this channel first */
+  if (!(chan->state == CHANNEL_STATE_CLOSING ||
+        chan->state == CHANNEL_STATE_CLOSED ||
+        chan->state == CHANNEL_STATE_ERROR)) {
+    memset(&cell, 0, sizeof(cell_t));
+    cell.circ_id = circ_id;
+    cell.command = CELL_DESTROY;
+    cell.payload[0] = (uint8_t) reason;
+    log_debug(LD_OR,
+              "Sending destroy (circID %d) on channel %p "
+              "(global ID " U64_FORMAT ")",
+              circ_id, chan,
+              U64_PRINTF_ARG(chan->global_identifier));
 
-  channel_write_cell(chan, &cell);
+    channel_write_cell(chan, &cell);
+  } else {
+    log_warn(LD_BUG,
+             "Someone called channel_send_destroy() for circID %d "
+             "on a channel " U64_FORMAT " at %p in state %s (%d)",
+             circ_id, U64_PRINTF_ARG(chan->global_identifier),
+             chan, channel_state_to_string(chan->state),
+             chan->state);
+  }
 
   return 0;
 }

+ 12 - 2
src/or/circuitlist.c

@@ -1411,7 +1411,12 @@ circuit_mark_for_close_(circuit_t *circ, int reason, int line,
   }
   if (circ->n_chan) {
     circuit_clear_cell_queue(circ, circ->n_chan);
-    channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
+    /* Only send destroy if the channel isn't closing anyway */
+    if (!(circ->n_chan->state == CHANNEL_STATE_CLOSING ||
+          circ->n_chan->state == CHANNEL_STATE_CLOSED ||
+          circ->n_chan->state == CHANNEL_STATE_ERROR)) {
+      channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
+    }
     circuitmux_detach_circuit(circ->n_chan->cmux, circ);
   }
 
@@ -1439,7 +1444,12 @@ circuit_mark_for_close_(circuit_t *circ, int reason, int line,
 
     if (or_circ->p_chan) {
       circuit_clear_cell_queue(circ, or_circ->p_chan);
-      channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
+      /* Only send destroy if the channel isn't closing anyway */
+      if (!(or_circ->p_chan->state == CHANNEL_STATE_CLOSING ||
+            or_circ->p_chan->state == CHANNEL_STATE_CLOSED ||
+            or_circ->p_chan->state == CHANNEL_STATE_ERROR)) {
+        channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
+      }
       circuitmux_detach_circuit(or_circ->p_chan->cmux, circ);
     }
   } else {