|  | @@ -210,6 +210,14 @@ typedef struct client_channel_channel_data {
 | 
	
		
			
				|  |  |    char* info_service_config_json;
 | 
	
		
			
				|  |  |  } channel_data;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +typedef struct {
 | 
	
		
			
				|  |  | +  channel_data* chand;
 | 
	
		
			
				|  |  | +  /** used as an identifier, don't dereference it because the LB policy may be
 | 
	
		
			
				|  |  | +   * non-existing when the callback is run */
 | 
	
		
			
				|  |  | +  grpc_lb_policy* lb_policy;
 | 
	
		
			
				|  |  | +  grpc_closure closure;
 | 
	
		
			
				|  |  | +} reresolution_request_args;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /** We create one watcher for each new lb_policy that is returned from a
 | 
	
		
			
				|  |  |      resolver, to watch for state changes from the lb_policy. When a state
 | 
	
		
			
				|  |  |      change is seen, we update the channel, and create a new watcher. */
 | 
	
	
		
			
				|  | @@ -258,21 +266,13 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |  static void on_lb_policy_state_changed_locked(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |                                                void* arg, grpc_error* error) {
 | 
	
		
			
				|  |  |    lb_policy_connectivity_watcher* w = (lb_policy_connectivity_watcher*)arg;
 | 
	
		
			
				|  |  | -  grpc_connectivity_state publish_state = w->state;
 | 
	
		
			
				|  |  |    /* check if the notification is for the latest policy */
 | 
	
		
			
				|  |  |    if (w->lb_policy == w->chand->lb_policy) {
 | 
	
		
			
				|  |  |      if (grpc_client_channel_trace.enabled()) {
 | 
	
		
			
				|  |  |        gpr_log(GPR_DEBUG, "chand=%p: lb_policy=%p state changed to %s", w->chand,
 | 
	
		
			
				|  |  |                w->lb_policy, grpc_connectivity_state_name(w->state));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if (publish_state == GRPC_CHANNEL_SHUTDOWN &&
 | 
	
		
			
				|  |  | -        w->chand->resolver != nullptr) {
 | 
	
		
			
				|  |  | -      publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
 | 
	
		
			
				|  |  | -      grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
 | 
	
		
			
				|  |  | -      GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
 | 
	
		
			
				|  |  | -      w->chand->lb_policy = nullptr;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
 | 
	
		
			
				|  |  | +    set_channel_connectivity_state_locked(exec_ctx, w->chand, w->state,
 | 
	
		
			
				|  |  |                                            GRPC_ERROR_REF(error), "lb_changed");
 | 
	
		
			
				|  |  |      if (w->state != GRPC_CHANNEL_SHUTDOWN) {
 | 
	
		
			
				|  |  |        watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
 | 
	
	
		
			
				|  | @@ -369,6 +369,27 @@ static void parse_retry_throttle_params(const grpc_json* field, void* arg) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void request_reresolution_locked(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  | +                                        grpc_error* error) {
 | 
	
		
			
				|  |  | +  reresolution_request_args* args = (reresolution_request_args*)arg;
 | 
	
		
			
				|  |  | +  channel_data* chand = args->chand;
 | 
	
		
			
				|  |  | +  // If this invocation is for a stale LB policy, treat it as an LB shutdown
 | 
	
		
			
				|  |  | +  // signal.
 | 
	
		
			
				|  |  | +  if (args->lb_policy != chand->lb_policy || error != GRPC_ERROR_NONE ||
 | 
	
		
			
				|  |  | +      chand->resolver == nullptr) {
 | 
	
		
			
				|  |  | +    GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "re-resolution");
 | 
	
		
			
				|  |  | +    gpr_free(args);
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (grpc_client_channel_trace.enabled()) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_DEBUG, "chand=%p: started name re-resolving", chand);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  grpc_resolver_channel_saw_error_locked(exec_ctx, chand->resolver);
 | 
	
		
			
				|  |  | +  // Give back the closure to the LB policy.
 | 
	
		
			
				|  |  | +  grpc_lb_policy_set_reresolve_closure_locked(exec_ctx, chand->lb_policy,
 | 
	
		
			
				|  |  | +                                              &args->closure);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void on_resolver_result_changed_locked(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |                                                void* arg, grpc_error* error) {
 | 
	
		
			
				|  |  |    channel_data* chand = (channel_data*)arg;
 | 
	
	
		
			
				|  | @@ -385,100 +406,114 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |    grpc_server_retry_throttle_data* retry_throttle_data = nullptr;
 | 
	
		
			
				|  |  |    grpc_slice_hash_table* method_params_table = nullptr;
 | 
	
		
			
				|  |  |    if (chand->resolver_result != nullptr) {
 | 
	
		
			
				|  |  | -    // Find LB policy name.
 | 
	
		
			
				|  |  | -    const char* lb_policy_name = nullptr;
 | 
	
		
			
				|  |  | -    const grpc_arg* channel_arg =
 | 
	
		
			
				|  |  | -        grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
 | 
	
		
			
				|  |  | -    if (channel_arg != nullptr) {
 | 
	
		
			
				|  |  | -      GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
 | 
	
		
			
				|  |  | -      lb_policy_name = channel_arg->value.string;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // Special case: If at least one balancer address is present, we use
 | 
	
		
			
				|  |  | -    // the grpclb policy, regardless of what the resolver actually specified.
 | 
	
		
			
				|  |  | -    channel_arg =
 | 
	
		
			
				|  |  | -        grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
 | 
	
		
			
				|  |  | -    if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_POINTER) {
 | 
	
		
			
				|  |  | -      grpc_lb_addresses* addresses =
 | 
	
		
			
				|  |  | -          (grpc_lb_addresses*)channel_arg->value.pointer.p;
 | 
	
		
			
				|  |  | -      bool found_balancer_address = false;
 | 
	
		
			
				|  |  | -      for (size_t i = 0; i < addresses->num_addresses; ++i) {
 | 
	
		
			
				|  |  | -        if (addresses->addresses[i].is_balancer) {
 | 
	
		
			
				|  |  | -          found_balancer_address = true;
 | 
	
		
			
				|  |  | -          break;
 | 
	
		
			
				|  |  | +    if (chand->resolver != nullptr) {
 | 
	
		
			
				|  |  | +      // Find LB policy name.
 | 
	
		
			
				|  |  | +      const char* lb_policy_name = nullptr;
 | 
	
		
			
				|  |  | +      const grpc_arg* channel_arg = grpc_channel_args_find(
 | 
	
		
			
				|  |  | +          chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
 | 
	
		
			
				|  |  | +      if (channel_arg != nullptr) {
 | 
	
		
			
				|  |  | +        GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
 | 
	
		
			
				|  |  | +        lb_policy_name = channel_arg->value.string;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      // Special case: If at least one balancer address is present, we use
 | 
	
		
			
				|  |  | +      // the grpclb policy, regardless of what the resolver actually specified.
 | 
	
		
			
				|  |  | +      channel_arg =
 | 
	
		
			
				|  |  | +          grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
 | 
	
		
			
				|  |  | +      if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_POINTER) {
 | 
	
		
			
				|  |  | +        grpc_lb_addresses* addresses =
 | 
	
		
			
				|  |  | +            (grpc_lb_addresses*)channel_arg->value.pointer.p;
 | 
	
		
			
				|  |  | +        bool found_balancer_address = false;
 | 
	
		
			
				|  |  | +        for (size_t i = 0; i < addresses->num_addresses; ++i) {
 | 
	
		
			
				|  |  | +          if (addresses->addresses[i].is_balancer) {
 | 
	
		
			
				|  |  | +            found_balancer_address = true;
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (found_balancer_address) {
 | 
	
		
			
				|  |  | +          if (lb_policy_name != nullptr &&
 | 
	
		
			
				|  |  | +              strcmp(lb_policy_name, "grpclb") != 0) {
 | 
	
		
			
				|  |  | +            gpr_log(GPR_INFO,
 | 
	
		
			
				|  |  | +                    "resolver requested LB policy %s but provided at least one "
 | 
	
		
			
				|  |  | +                    "balancer address -- forcing use of grpclb LB policy",
 | 
	
		
			
				|  |  | +                    lb_policy_name);
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          lb_policy_name = "grpclb";
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      if (found_balancer_address) {
 | 
	
		
			
				|  |  | -        if (lb_policy_name != nullptr &&
 | 
	
		
			
				|  |  | -            strcmp(lb_policy_name, "grpclb") != 0) {
 | 
	
		
			
				|  |  | -          gpr_log(GPR_INFO,
 | 
	
		
			
				|  |  | -                  "resolver requested LB policy %s but provided at least one "
 | 
	
		
			
				|  |  | -                  "balancer address -- forcing use of grpclb LB policy",
 | 
	
		
			
				|  |  | +      // Use pick_first if nothing was specified and we didn't select grpclb
 | 
	
		
			
				|  |  | +      // above.
 | 
	
		
			
				|  |  | +      if (lb_policy_name == nullptr) lb_policy_name = "pick_first";
 | 
	
		
			
				|  |  | +      grpc_lb_policy_args lb_policy_args;
 | 
	
		
			
				|  |  | +      lb_policy_args.args = chand->resolver_result;
 | 
	
		
			
				|  |  | +      lb_policy_args.client_channel_factory = chand->client_channel_factory;
 | 
	
		
			
				|  |  | +      lb_policy_args.combiner = chand->combiner;
 | 
	
		
			
				|  |  | +      // Check to see if we're already using the right LB policy.
 | 
	
		
			
				|  |  | +      // Note: It's safe to use chand->info_lb_policy_name here without
 | 
	
		
			
				|  |  | +      // taking a lock on chand->info_mu, because this function is the
 | 
	
		
			
				|  |  | +      // only thing that modifies its value, and it can only be invoked
 | 
	
		
			
				|  |  | +      // once at any given time.
 | 
	
		
			
				|  |  | +      lb_policy_name_changed =
 | 
	
		
			
				|  |  | +          chand->info_lb_policy_name == nullptr ||
 | 
	
		
			
				|  |  | +          gpr_stricmp(chand->info_lb_policy_name, lb_policy_name) != 0;
 | 
	
		
			
				|  |  | +      if (chand->lb_policy != nullptr && !lb_policy_name_changed) {
 | 
	
		
			
				|  |  | +        // Continue using the same LB policy.  Update with new addresses.
 | 
	
		
			
				|  |  | +        lb_policy_updated = true;
 | 
	
		
			
				|  |  | +        grpc_lb_policy_update_locked(exec_ctx, chand->lb_policy,
 | 
	
		
			
				|  |  | +                                     &lb_policy_args);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        // Instantiate new LB policy.
 | 
	
		
			
				|  |  | +        new_lb_policy =
 | 
	
		
			
				|  |  | +            grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
 | 
	
		
			
				|  |  | +        if (new_lb_policy == nullptr) {
 | 
	
		
			
				|  |  | +          gpr_log(GPR_ERROR, "could not create LB policy \"%s\"",
 | 
	
		
			
				|  |  |                    lb_policy_name);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          reresolution_request_args* args =
 | 
	
		
			
				|  |  | +              (reresolution_request_args*)gpr_zalloc(sizeof(*args));
 | 
	
		
			
				|  |  | +          args->chand = chand;
 | 
	
		
			
				|  |  | +          args->lb_policy = new_lb_policy;
 | 
	
		
			
				|  |  | +          GRPC_CLOSURE_INIT(&args->closure, request_reresolution_locked, args,
 | 
	
		
			
				|  |  | +                            grpc_combiner_scheduler(chand->combiner));
 | 
	
		
			
				|  |  | +          GRPC_CHANNEL_STACK_REF(chand->owning_stack, "re-resolution");
 | 
	
		
			
				|  |  | +          grpc_lb_policy_set_reresolve_closure_locked(exec_ctx, new_lb_policy,
 | 
	
		
			
				|  |  | +                                                      &args->closure);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        lb_policy_name = "grpclb";
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // Use pick_first if nothing was specified and we didn't select grpclb
 | 
	
		
			
				|  |  | -    // above.
 | 
	
		
			
				|  |  | -    if (lb_policy_name == nullptr) lb_policy_name = "pick_first";
 | 
	
		
			
				|  |  | -    grpc_lb_policy_args lb_policy_args;
 | 
	
		
			
				|  |  | -    lb_policy_args.args = chand->resolver_result;
 | 
	
		
			
				|  |  | -    lb_policy_args.client_channel_factory = chand->client_channel_factory;
 | 
	
		
			
				|  |  | -    lb_policy_args.combiner = chand->combiner;
 | 
	
		
			
				|  |  | -    // Check to see if we're already using the right LB policy.
 | 
	
		
			
				|  |  | -    // Note: It's safe to use chand->info_lb_policy_name here without
 | 
	
		
			
				|  |  | -    // taking a lock on chand->info_mu, because this function is the
 | 
	
		
			
				|  |  | -    // only thing that modifies its value, and it can only be invoked
 | 
	
		
			
				|  |  | -    // once at any given time.
 | 
	
		
			
				|  |  | -    lb_policy_name_changed =
 | 
	
		
			
				|  |  | -        chand->info_lb_policy_name == nullptr ||
 | 
	
		
			
				|  |  | -        gpr_stricmp(chand->info_lb_policy_name, lb_policy_name) != 0;
 | 
	
		
			
				|  |  | -    if (chand->lb_policy != nullptr && !lb_policy_name_changed) {
 | 
	
		
			
				|  |  | -      // Continue using the same LB policy.  Update with new addresses.
 | 
	
		
			
				|  |  | -      lb_policy_updated = true;
 | 
	
		
			
				|  |  | -      grpc_lb_policy_update_locked(exec_ctx, chand->lb_policy, &lb_policy_args);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      // Instantiate new LB policy.
 | 
	
		
			
				|  |  | -      new_lb_policy =
 | 
	
		
			
				|  |  | -          grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
 | 
	
		
			
				|  |  | -      if (new_lb_policy == nullptr) {
 | 
	
		
			
				|  |  | -        gpr_log(GPR_ERROR, "could not create LB policy \"%s\"", lb_policy_name);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // Find service config.
 | 
	
		
			
				|  |  | -    channel_arg =
 | 
	
		
			
				|  |  | -        grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
 | 
	
		
			
				|  |  | -    if (channel_arg != nullptr) {
 | 
	
		
			
				|  |  | -      GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
 | 
	
		
			
				|  |  | -      service_config_json = gpr_strdup(channel_arg->value.string);
 | 
	
		
			
				|  |  | -      grpc_service_config* service_config =
 | 
	
		
			
				|  |  | -          grpc_service_config_create(service_config_json);
 | 
	
		
			
				|  |  | -      if (service_config != nullptr) {
 | 
	
		
			
				|  |  | -        channel_arg =
 | 
	
		
			
				|  |  | -            grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
 | 
	
		
			
				|  |  | -        GPR_ASSERT(channel_arg != nullptr);
 | 
	
		
			
				|  |  | +      // Find service config.
 | 
	
		
			
				|  |  | +      channel_arg = grpc_channel_args_find(chand->resolver_result,
 | 
	
		
			
				|  |  | +                                           GRPC_ARG_SERVICE_CONFIG);
 | 
	
		
			
				|  |  | +      if (channel_arg != nullptr) {
 | 
	
		
			
				|  |  |          GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
 | 
	
		
			
				|  |  | -        grpc_uri* uri =
 | 
	
		
			
				|  |  | -            grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
 | 
	
		
			
				|  |  | -        GPR_ASSERT(uri->path[0] != '\0');
 | 
	
		
			
				|  |  | -        service_config_parsing_state parsing_state;
 | 
	
		
			
				|  |  | -        memset(&parsing_state, 0, sizeof(parsing_state));
 | 
	
		
			
				|  |  | -        parsing_state.server_name =
 | 
	
		
			
				|  |  | -            uri->path[0] == '/' ? uri->path + 1 : uri->path;
 | 
	
		
			
				|  |  | -        grpc_service_config_parse_global_params(
 | 
	
		
			
				|  |  | -            service_config, parse_retry_throttle_params, &parsing_state);
 | 
	
		
			
				|  |  | -        grpc_uri_destroy(uri);
 | 
	
		
			
				|  |  | -        retry_throttle_data = parsing_state.retry_throttle_data;
 | 
	
		
			
				|  |  | -        method_params_table = grpc_service_config_create_method_config_table(
 | 
	
		
			
				|  |  | -            exec_ctx, service_config, method_parameters_create_from_json,
 | 
	
		
			
				|  |  | -            method_parameters_ref_wrapper, method_parameters_unref_wrapper);
 | 
	
		
			
				|  |  | -        grpc_service_config_destroy(service_config);
 | 
	
		
			
				|  |  | +        service_config_json = gpr_strdup(channel_arg->value.string);
 | 
	
		
			
				|  |  | +        grpc_service_config* service_config =
 | 
	
		
			
				|  |  | +            grpc_service_config_create(service_config_json);
 | 
	
		
			
				|  |  | +        if (service_config != nullptr) {
 | 
	
		
			
				|  |  | +          channel_arg = grpc_channel_args_find(chand->resolver_result,
 | 
	
		
			
				|  |  | +                                               GRPC_ARG_SERVER_URI);
 | 
	
		
			
				|  |  | +          GPR_ASSERT(channel_arg != nullptr);
 | 
	
		
			
				|  |  | +          GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
 | 
	
		
			
				|  |  | +          grpc_uri* uri =
 | 
	
		
			
				|  |  | +              grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
 | 
	
		
			
				|  |  | +          GPR_ASSERT(uri->path[0] != '\0');
 | 
	
		
			
				|  |  | +          service_config_parsing_state parsing_state;
 | 
	
		
			
				|  |  | +          memset(&parsing_state, 0, sizeof(parsing_state));
 | 
	
		
			
				|  |  | +          parsing_state.server_name =
 | 
	
		
			
				|  |  | +              uri->path[0] == '/' ? uri->path + 1 : uri->path;
 | 
	
		
			
				|  |  | +          grpc_service_config_parse_global_params(
 | 
	
		
			
				|  |  | +              service_config, parse_retry_throttle_params, &parsing_state);
 | 
	
		
			
				|  |  | +          grpc_uri_destroy(uri);
 | 
	
		
			
				|  |  | +          retry_throttle_data = parsing_state.retry_throttle_data;
 | 
	
		
			
				|  |  | +          method_params_table = grpc_service_config_create_method_config_table(
 | 
	
		
			
				|  |  | +              exec_ctx, service_config, method_parameters_create_from_json,
 | 
	
		
			
				|  |  | +              method_parameters_ref_wrapper, method_parameters_unref_wrapper);
 | 
	
		
			
				|  |  | +          grpc_service_config_destroy(service_config);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +      // Before we clean up, save a copy of lb_policy_name, since it might
 | 
	
		
			
				|  |  | +      // be pointing to data inside chand->resolver_result.
 | 
	
		
			
				|  |  | +      // The copy will be saved in chand->lb_policy_name below.
 | 
	
		
			
				|  |  | +      lb_policy_name_dup = gpr_strdup(lb_policy_name);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    // Before we clean up, save a copy of lb_policy_name, since it might
 | 
	
		
			
				|  |  | -    // be pointing to data inside chand->resolver_result.
 | 
	
		
			
				|  |  | -    // The copy will be saved in chand->lb_policy_name below.
 | 
	
		
			
				|  |  | -    lb_policy_name_dup = gpr_strdup(lb_policy_name);
 | 
	
		
			
				|  |  |      grpc_channel_args_destroy(exec_ctx, chand->resolver_result);
 | 
	
		
			
				|  |  |      chand->resolver_result = nullptr;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -515,11 +550,11 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    chand->method_params_table = method_params_table;
 | 
	
		
			
				|  |  |    // If we have a new LB policy or are shutting down (in which case
 | 
	
		
			
				|  |  | -  // new_lb_policy will be NULL), swap out the LB policy, unreffing the
 | 
	
		
			
				|  |  | -  // old one and removing its fds from chand->interested_parties.
 | 
	
		
			
				|  |  | -  // Note that we do NOT do this if either (a) we updated the existing
 | 
	
		
			
				|  |  | -  // LB policy above or (b) we failed to create the new LB policy (in
 | 
	
		
			
				|  |  | -  // which case we want to continue using the most recent one we had).
 | 
	
		
			
				|  |  | +  // new_lb_policy will be NULL), swap out the LB policy, unreffing the old one
 | 
	
		
			
				|  |  | +  // and removing its fds from chand->interested_parties. Note that we do NOT do
 | 
	
		
			
				|  |  | +  // this if either (a) we updated the existing LB policy above or (b) we failed
 | 
	
		
			
				|  |  | +  // to create the new LB policy (in which case we want to continue using the
 | 
	
		
			
				|  |  | +  // most recent one we had).
 | 
	
		
			
				|  |  |    if (new_lb_policy != nullptr || error != GRPC_ERROR_NONE ||
 | 
	
		
			
				|  |  |        chand->resolver == nullptr) {
 | 
	
		
			
				|  |  |      if (chand->lb_policy != nullptr) {
 |