|  | @@ -43,9 +43,66 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  | +#include <grpc/support/useful.h>
 | 
	
		
			
				|  |  |  #include "src/core/iomgr/fd_posix.h"
 | 
	
		
			
				|  |  | -#include "src/core/support/block_annotate.h"
 | 
	
		
			
				|  |  |  #include "src/core/profiling/timers.h"
 | 
	
		
			
				|  |  | +#include "src/core/support/block_annotate.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct epoll_fd_list {
 | 
	
		
			
				|  |  | +  int *epoll_fds;
 | 
	
		
			
				|  |  | +  size_t count;
 | 
	
		
			
				|  |  | +  size_t capacity;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static struct epoll_fd_list epoll_fd_global_list;
 | 
	
		
			
				|  |  | +static gpr_once init_epoll_fd_list_mu = GPR_ONCE_INIT;
 | 
	
		
			
				|  |  | +static gpr_mu epoll_fd_list_mu;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void init_mu(void) { gpr_mu_init(&epoll_fd_list_mu); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void add_epoll_fd_to_global_list(int epoll_fd) {
 | 
	
		
			
				|  |  | +  gpr_once_init(&init_epoll_fd_list_mu, init_mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&epoll_fd_list_mu);
 | 
	
		
			
				|  |  | +  if (epoll_fd_global_list.count == epoll_fd_global_list.capacity) {
 | 
	
		
			
				|  |  | +    epoll_fd_global_list.capacity =
 | 
	
		
			
				|  |  | +        GPR_MAX((size_t)8, epoll_fd_global_list.capacity * 2);
 | 
	
		
			
				|  |  | +    epoll_fd_global_list.epoll_fds =
 | 
	
		
			
				|  |  | +        gpr_realloc(epoll_fd_global_list.epoll_fds,
 | 
	
		
			
				|  |  | +                    epoll_fd_global_list.capacity * sizeof(int));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  epoll_fd_global_list.epoll_fds[epoll_fd_global_list.count++] = epoll_fd;
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&epoll_fd_list_mu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void remove_epoll_fd_from_global_list(int epoll_fd) {
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&epoll_fd_list_mu);
 | 
	
		
			
				|  |  | +  GPR_ASSERT(epoll_fd_global_list.count > 0);
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < epoll_fd_global_list.count; i++) {
 | 
	
		
			
				|  |  | +    if (epoll_fd == epoll_fd_global_list.epoll_fds[i]) {
 | 
	
		
			
				|  |  | +      epoll_fd_global_list.epoll_fds[i] =
 | 
	
		
			
				|  |  | +          epoll_fd_global_list.epoll_fds[--(epoll_fd_global_list.count)];
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&epoll_fd_list_mu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_remove_fd_from_all_epoll_sets(int fd) {
 | 
	
		
			
				|  |  | +  int err;
 | 
	
		
			
				|  |  | +  gpr_mu_lock(&epoll_fd_list_mu);
 | 
	
		
			
				|  |  | +  if (epoll_fd_global_list.count == 0) {
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < epoll_fd_global_list.count; i++) {
 | 
	
		
			
				|  |  | +    err = epoll_ctl(epoll_fd_global_list.epoll_fds[i], EPOLL_CTL_DEL, fd, NULL);
 | 
	
		
			
				|  |  | +    if (err < 0 && errno != ENOENT) {
 | 
	
		
			
				|  |  | +      gpr_log(GPR_ERROR, "epoll_ctl del for %d failed: %s", fd,
 | 
	
		
			
				|  |  | +              strerror(errno));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  gpr_mu_unlock(&epoll_fd_list_mu);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
		
			
				|  |  |    grpc_pollset *pollset;
 | 
	
	
		
			
				|  | @@ -211,6 +268,7 @@ static void multipoll_with_epoll_pollset_finish_shutdown(
 | 
	
		
			
				|  |  |  static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) {
 | 
	
		
			
				|  |  |    pollset_hdr *h = pollset->data.ptr;
 | 
	
		
			
				|  |  |    close(h->epoll_fd);
 | 
	
		
			
				|  |  | +  remove_epoll_fd_from_global_list(h->epoll_fd);
 | 
	
		
			
				|  |  |    gpr_free(h);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -236,6 +294,7 @@ static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "epoll_create1 failed: %s", strerror(errno));
 | 
	
		
			
				|  |  |      abort();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  add_epoll_fd_to_global_list(h->epoll_fd);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    ev.events = (uint32_t)(EPOLLIN | EPOLLET);
 | 
	
		
			
				|  |  |    ev.data.ptr = NULL;
 | 
	
	
		
			
				|  | @@ -255,4 +314,8 @@ static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx,
 | 
	
		
			
				|  |  |  grpc_platform_become_multipoller_type grpc_platform_become_multipoller =
 | 
	
		
			
				|  |  |      epoll_become_multipoller;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#else /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void grpc_remove_fd_from_all_epoll_sets(int fd) {}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */
 |