Refcounting fixes
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
index 6f4bf2e..3d06576 100644
--- a/src/core/client_config/subchannel.c
+++ b/src/core/client_config/subchannel.c
@@ -123,13 +123,29 @@
 static gpr_timespec compute_connect_deadline(grpc_subchannel *c);
 static void subchannel_connected(void *subchannel, int iomgr_success);
 
-static void subchannel_ref_locked(grpc_subchannel *c);
-static int subchannel_unref_locked(grpc_subchannel *c) GRPC_MUST_USE_RESULT;
-static void connection_ref_locked(connection *c);
-static grpc_subchannel *connection_unref_locked(connection *c)
+static void subchannel_ref_locked(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+static int subchannel_unref_locked(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) GRPC_MUST_USE_RESULT;
+static void connection_ref_locked(connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+static grpc_subchannel *connection_unref_locked(connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS)
     GRPC_MUST_USE_RESULT;
 static void subchannel_destroy(grpc_subchannel *c);
 
+#ifdef GRPC_SUBCHANNEL_REFCOUNT_DEBUG
+#define SUBCHANNEL_REF_LOCKED(p, r) subchannel_ref_locked((p), __FILE__, __LINE__, (r))
+#define SUBCHANNEL_UNREF_LOCKED(p, r) subchannel_unref_locked((p), __FILE__, __LINE__, (r))
+#define CONNECTION_REF_LOCKED(p, r) connection_ref_locked((p), __FILE__, __LINE__, (r))
+#define CONNECTION_UNREF_LOCKED(p, r) connection_unref_locked((p), __FILE__, __LINE__, (r))
+#define REF_PASS_ARGS , file, line, reason
+#define REF_LOG(name, p) gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p   ref %d -> %d %s", (name), (p), (p)->refs, (p)->refs + 1, reason)
+#define UNREF_LOG(name, p) gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p unref %d -> %d %s", (name), (p), (p)->refs, (p)->refs - 1, reason)
+#else
+#define SUBCHANNEL_REF_LOCKED(p, r) subchannel_ref_locked((p))
+#define SUBCHANNEL_UNREF_LOCKED(p, r) subchannel_unref_locked((p))
+#define CONNECTION_REF_LOCKED(p, r) connection_ref_locked((p), __FILE__, __LINE__, (r))
+#define CONNECTION_UNREF_LOCKED(p, r) connection_unref_locked((p), __FILE__, __LINE__, (r))
+#define REF_PASS_ARGS
+#endif
+
 /*
  * connection implementation
  */
@@ -140,14 +156,16 @@
   gpr_free(c);
 }
 
-static void connection_ref_locked(connection *c) {
-  subchannel_ref_locked(c->subchannel);
+static void connection_ref_locked(connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  REF_LOG("CONNECTION", c);
+  subchannel_ref_locked(c->subchannel REF_PASS_ARGS);
   ++c->refs;
 }
 
-static grpc_subchannel *connection_unref_locked(connection *c) {
+static grpc_subchannel *connection_unref_locked(connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
   grpc_subchannel *destroy = NULL;
-  if (subchannel_unref_locked(c->subchannel)) {
+  UNREF_LOG("CONNECTION", c);
+  if (subchannel_unref_locked(c->subchannel REF_PASS_ARGS)) {
     destroy = c->subchannel;
   }
   if (--c->refs == 0 && c->subchannel->active != c) {
@@ -160,22 +178,26 @@
  * grpc_subchannel implementation
  */
 
-static void subchannel_ref_locked(grpc_subchannel *c) { ++c->refs; }
+static void subchannel_ref_locked(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { 
+  REF_LOG("SUBCHANNEL", c);
+  ++c->refs; 
+}
 
-static int subchannel_unref_locked(grpc_subchannel *c) {
+static int subchannel_unref_locked(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
+  UNREF_LOG("SUBCHANNEL", c);
   return --c->refs == 0;
 }
 
-void grpc_subchannel_ref(grpc_subchannel *c) {
+void grpc_subchannel_ref(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
   gpr_mu_lock(&c->mu);
-  subchannel_ref_locked(c);
+  subchannel_ref_locked(c REF_PASS_ARGS);
   gpr_mu_unlock(&c->mu);
 }
 
-void grpc_subchannel_unref(grpc_subchannel *c) {
+void grpc_subchannel_unref(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
   int destroy;
   gpr_mu_lock(&c->mu);
-  destroy = subchannel_unref_locked(c);
+  destroy = subchannel_unref_locked(c REF_PASS_ARGS);
   gpr_mu_unlock(&c->mu);
   if (destroy) subchannel_destroy(c);
 }
@@ -190,6 +212,7 @@
   grpc_mdctx_unref(c->mdctx);
   grpc_pollset_set_destroy(&c->pollset_set);
   grpc_connectivity_state_destroy(&c->state_tracker);
+  grpc_connector_unref(c->connector);
   gpr_free(c);
 }
 
@@ -246,7 +269,7 @@
   waiting_for_connect *w4c = arg;
   grpc_subchannel_create_call(w4c->subchannel, &w4c->initial_op, w4c->target,
                               w4c->notify);
-  grpc_subchannel_unref(w4c->subchannel);
+  GRPC_SUBCHANNEL_UNREF(w4c->subchannel, "waiting_for_connect");
   gpr_free(w4c);
 }
 
@@ -258,7 +281,7 @@
   gpr_mu_lock(&c->mu);
   if (c->active != NULL) {
     con = c->active;
-    connection_ref_locked(con);
+    CONNECTION_REF_LOCKED(con, "call");
     gpr_mu_unlock(&c->mu);
 
     *target = create_call(con, initial_op);
@@ -271,7 +294,7 @@
     w4c->target = target;
     w4c->subchannel = c;
     /* released when clearing w4c */
-    subchannel_ref_locked(c);
+    SUBCHANNEL_REF_LOCKED(c, "waiting_for_connect");
     grpc_iomgr_closure_init(&w4c->continuation, continue_creating_call, w4c);
     c->waiting = w4c;
     grpc_subchannel_add_interested_party(c, initial_op->bind_pollset);
@@ -279,7 +302,7 @@
       c->connecting = 1;
       connectivity_state_changed_locked(c);
       /* released by connection */
-      subchannel_ref_locked(c);
+      SUBCHANNEL_REF_LOCKED(c, "connecting");
       gpr_mu_unlock(&c->mu);
 
       start_connect(c);
@@ -307,7 +330,7 @@
     do_connect = 1;
     c->connecting = 1;
     /* released by connection */
-    subchannel_ref_locked(c);
+    SUBCHANNEL_REF_LOCKED(c, "connecting");
     grpc_connectivity_state_set(&c->state_tracker,
                                 compute_connectivity_locked(c));
   }
@@ -365,7 +388,7 @@
     case GRPC_CHANNEL_TRANSIENT_FAILURE:
       /* things are starting to go wrong, reconnect but don't deactivate */
       /* released by connection */
-      subchannel_ref_locked(c);
+      SUBCHANNEL_REF_LOCKED(c, "connection");
       do_connect = 1;
       c->connecting = 1;
       break;
@@ -374,7 +397,7 @@
 done:
   grpc_connectivity_state_set(&c->state_tracker,
                               compute_connectivity_locked(c));
-  destroy = subchannel_unref_locked(c);
+  destroy = SUBCHANNEL_UNREF_LOCKED(c, "connection");
   gpr_free(sw);
   gpr_mu_unlock(mu);
   if (do_connect) {
@@ -468,7 +491,7 @@
   } else {
     int destroy;
     gpr_mu_lock(&c->mu);
-    destroy = subchannel_unref_locked(c);
+    destroy = SUBCHANNEL_UNREF_LOCKED(c, "connection");
     gpr_mu_unlock(&c->mu);
     if (destroy) subchannel_destroy(c);
     /* TODO(ctiller): retry after sleeping */
@@ -499,18 +522,20 @@
  * grpc_subchannel_call implementation
  */
 
-void grpc_subchannel_call_ref(grpc_subchannel_call *c) { gpr_ref(&c->refs); }
+void grpc_subchannel_call_ref(grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { 
+  gpr_ref(&c->refs); 
+}
 
-void grpc_subchannel_call_unref(grpc_subchannel_call *c) {
+void grpc_subchannel_call_unref(grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
   if (gpr_unref(&c->refs)) {
     gpr_mu *mu = &c->connection->subchannel->mu;
     grpc_subchannel *destroy;
     grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c));
     gpr_mu_lock(mu);
-    destroy = connection_unref_locked(c->connection);
+    destroy = CONNECTION_UNREF_LOCKED(c->connection, "call");
     gpr_mu_unlock(mu);
     gpr_free(c);
-    if (destroy) {
+    if (destroy != NULL) {
       subchannel_destroy(destroy);
     }
   }