|  | @@ -67,7 +67,6 @@
 | 
	
		
			
				|  |  |  #include <grpc/support/sync.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/time.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define INIT_PORT_CAP 2
 | 
	
		
			
				|  |  |  #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static gpr_once s_init_max_accept_queue_size;
 | 
	
	
		
			
				|  | @@ -89,8 +88,12 @@ struct grpc_tcp_listener {
 | 
	
		
			
				|  |  |    grpc_closure destroyed_closure;
 | 
	
		
			
				|  |  |    gpr_refcount refs;
 | 
	
		
			
				|  |  |    struct grpc_tcp_listener *next;
 | 
	
		
			
				|  |  | -  struct grpc_tcp_listener *dual_stack_second_port;
 | 
	
		
			
				|  |  | -  int is_dual_stack_second_port;
 | 
	
		
			
				|  |  | +  /* When we add a listener, more than one can be created, mainly because of
 | 
	
		
			
				|  |  | +     IPv6. A sibling will still be in the normal list, but will be flagged
 | 
	
		
			
				|  |  | +     as such. Any action, such as ref or unref, will affect all of the
 | 
	
		
			
				|  |  | +     siblings in the list. */
 | 
	
		
			
				|  |  | +  struct grpc_tcp_listener *sibling;
 | 
	
		
			
				|  |  | +  int is_sibling;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
 | 
	
	
		
			
				|  | @@ -394,8 +397,8 @@ static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
 | 
	
		
			
				|  |  |      memcpy(sp->addr.untyped, addr, addr_len);
 | 
	
		
			
				|  |  |      sp->addr_len = addr_len;
 | 
	
		
			
				|  |  |      sp->port = port;
 | 
	
		
			
				|  |  | -    sp->is_dual_stack_second_port = 0;
 | 
	
		
			
				|  |  | -    sp->dual_stack_second_port = NULL;
 | 
	
		
			
				|  |  | +    sp->is_sibling = 0;
 | 
	
		
			
				|  |  | +    sp->sibling = NULL;
 | 
	
		
			
				|  |  |      gpr_ref_init(&sp->refs, 1);
 | 
	
		
			
				|  |  |      GPR_ASSERT(sp->emfd);
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&s->mu);
 | 
	
	
		
			
				|  | @@ -486,8 +489,8 @@ grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
 | 
	
		
			
				|  |  |      addr_len = sizeof(addr4_copy);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    sp = add_socket_to_server(s, fd, addr, addr_len);
 | 
	
		
			
				|  |  | -  sp->dual_stack_second_port = sp2;
 | 
	
		
			
				|  |  | -  if (sp2) sp2->is_dual_stack_second_port = 1;
 | 
	
		
			
				|  |  | +  sp->sibling = sp2;
 | 
	
		
			
				|  |  | +  if (sp2) sp2->is_sibling = 1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  done:
 | 
	
		
			
				|  |  |    gpr_free(allocated_addr);
 | 
	
	
		
			
				|  | @@ -543,9 +546,14 @@ void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void grpc_tcp_listener_unref(grpc_tcp_listener *listener) {
 | 
	
		
			
				|  |  |    grpc_tcp_listener *sp = listener;
 | 
	
		
			
				|  |  | -  if (sp->is_dual_stack_second_port) return;
 | 
	
		
			
				|  |  | +  if (sp->is_sibling) return;
 | 
	
		
			
				|  |  |    if (gpr_unref(&sp->refs)) {
 | 
	
		
			
				|  |  | -    if (sp->dual_stack_second_port) gpr_free(sp->dual_stack_second_port);
 | 
	
		
			
				|  |  | +    grpc_tcp_listener *sibling = sp->sibling;
 | 
	
		
			
				|  |  | +    while (sibling) {
 | 
	
		
			
				|  |  | +      sp = sibling;
 | 
	
		
			
				|  |  | +      sibling = sp->sibling;
 | 
	
		
			
				|  |  | +      gpr_free(sp);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      gpr_free(listener);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 |