|  | @@ -554,64 +554,95 @@ static void free_grpc_pollset(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
 | 
	
		
			
				|  |  |    grpc_closure destroyed;
 | 
	
		
			
				|  |  |    grpc_closure_init(&destroyed, destroy_pollset, pollset);
 | 
	
		
			
				|  |  |    grpc_pollset_shutdown(exec_ctx, pollset, &destroyed);
 | 
	
		
			
				|  |  | -  grpc_exec_ctx_finish(exec_ctx);
 | 
	
		
			
				|  |  | +  grpc_exec_ctx_flush(exec_ctx);
 | 
	
		
			
				|  |  |    gpr_free(pollset);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static void test_grpc_fd_read_notifier_pollset(void) {
 | 
	
		
			
				|  |  | +/* This tests that the read_notifier_pollset field of a grpc_fd is properly
 | 
	
		
			
				|  |  | +   set when the grpc_fd becomes readable
 | 
	
		
			
				|  |  | +   - This tests both basic and multi pollsets
 | 
	
		
			
				|  |  | +   - The parameter register_cb_after_read_event controls whether the on-read
 | 
	
		
			
				|  |  | +     callback registration (i.e the one done by grpc_fd_notify_on_read()) is
 | 
	
		
			
				|  |  | +     done either before or after the fd becomes readable
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static void test_grpc_fd_read_notifier_pollset(
 | 
	
		
			
				|  |  | +    bool register_cb_after_read_event) {
 | 
	
		
			
				|  |  |    grpc_fd *em_fd[2];
 | 
	
		
			
				|  |  | -  read_notifier_test_fd_context fd_context;
 | 
	
		
			
				|  |  |    int sv[2][2];
 | 
	
		
			
				|  |  | +  gpr_mu *mu[2];
 | 
	
		
			
				|  |  | +  grpc_pollset *pollset[2];
 | 
	
		
			
				|  |  |    char data;
 | 
	
		
			
				|  |  |    ssize_t result;
 | 
	
		
			
				|  |  |    int i;
 | 
	
		
			
				|  |  | +  grpc_pollset_worker *worker;
 | 
	
		
			
				|  |  | +  read_notifier_test_fd_context fd_context;
 | 
	
		
			
				|  |  |    grpc_closure on_read_closure;
 | 
	
		
			
				|  |  | -  gpr_mu *mu;
 | 
	
		
			
				|  |  |    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  grpc_pollset *pollset = create_grpc_pollset(&mu);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    for (i = 0; i < 2; i++) {
 | 
	
		
			
				|  |  | -    get_socket_pair(sv[i]);
 | 
	
		
			
				|  |  | +    pollset[i] = create_grpc_pollset(&mu[i]);
 | 
	
		
			
				|  |  | +    get_socket_pair(sv[i]); /* sv[i][0] & sv[i][1] will have the socket pair */
 | 
	
		
			
				|  |  | +    em_fd[i] = grpc_fd_create(sv[i][0], "test_grpc_fd_read_notifier_pollset");
 | 
	
		
			
				|  |  | +    grpc_pollset_add_fd(&exec_ctx, pollset[i], em_fd[i]);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    em_fd[i] = grpc_fd_create(sv[i][0], "test_grpc_fd_1_read_notifier_pollset");
 | 
	
		
			
				|  |  | +  /* At this point pollset[0] has em_fd[0] and pollset[1] has em_fd[1] and both
 | 
	
		
			
				|  |  | +     are basic pollsets. Make pollset[1] a multi-pollset by adding em_fd[0] to
 | 
	
		
			
				|  |  | +     it */
 | 
	
		
			
				|  |  | +  grpc_pollset_add_fd(&exec_ctx, pollset[1], em_fd[0]);
 | 
	
		
			
				|  |  | +  grpc_exec_ctx_flush(&exec_ctx);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    grpc_pollset_add_fd(&exec_ctx, pollset, em_fd[i]);
 | 
	
		
			
				|  |  | +  /* The following tests that the read_notifier_pollset is correctly set on the
 | 
	
		
			
				|  |  | +     grpc_fd structure in both basic pollset and multi pollset cases.
 | 
	
		
			
				|  |  | +      pollset[0] is a basic pollset containing just em_fd[0]
 | 
	
		
			
				|  |  | +      pollset[1] is a multi pollset containing em_fd[0] and em_fd[1] */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  for (i = 0; i < 2; i++) {
 | 
	
		
			
				|  |  |      on_read_closure.cb = read_notifier_test_callback;
 | 
	
		
			
				|  |  |      fd_context.fd = em_fd[i];
 | 
	
		
			
				|  |  |      fd_context.is_cb_called = false;
 | 
	
		
			
				|  |  |      on_read_closure.cb_arg = &fd_context;
 | 
	
		
			
				|  |  | -    grpc_fd_notify_on_read(&exec_ctx, em_fd[i], &on_read_closure);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!register_cb_after_read_event) {
 | 
	
		
			
				|  |  | +      /* Registering the callback BEFORE the fd is readable */
 | 
	
		
			
				|  |  | +      grpc_fd_notify_on_read(&exec_ctx, em_fd[i], &on_read_closure);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      data = 0;
 | 
	
		
			
				|  |  |      result = write(sv[i][1], &data, sizeof(data));
 | 
	
		
			
				|  |  |      GPR_ASSERT(result == 1);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    gpr_mu_lock(mu);
 | 
	
		
			
				|  |  | -    while (!fd_context.is_cb_called) {
 | 
	
		
			
				|  |  | -      grpc_pollset_worker *worker = NULL;
 | 
	
		
			
				|  |  | -      grpc_pollset_work(&exec_ctx, pollset, &worker,
 | 
	
		
			
				|  |  | -                        gpr_now(GPR_CLOCK_MONOTONIC),
 | 
	
		
			
				|  |  | -                        gpr_inf_future(GPR_CLOCK_MONOTONIC));
 | 
	
		
			
				|  |  | -      gpr_mu_unlock(mu);
 | 
	
		
			
				|  |  | -      grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  | -      gpr_mu_lock(mu);
 | 
	
		
			
				|  |  | +    /* grpc_pollset_work requires the caller to hold the pollset mutex */
 | 
	
		
			
				|  |  | +    gpr_mu_lock(mu[i]);
 | 
	
		
			
				|  |  | +    worker = NULL;
 | 
	
		
			
				|  |  | +    grpc_pollset_work(&exec_ctx, pollset[i], &worker,
 | 
	
		
			
				|  |  | +                      gpr_now(GPR_CLOCK_MONOTONIC),
 | 
	
		
			
				|  |  | +                      gpr_inf_future(GPR_CLOCK_MONOTONIC));
 | 
	
		
			
				|  |  | +    gpr_mu_unlock(mu[i]);
 | 
	
		
			
				|  |  | +    grpc_exec_ctx_flush(&exec_ctx);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (register_cb_after_read_event) {
 | 
	
		
			
				|  |  | +      /* Registering the callback after the fd is readable. In this case, the
 | 
	
		
			
				|  |  | +         callback should be executed right away. */
 | 
	
		
			
				|  |  | +      grpc_fd_notify_on_read(&exec_ctx, em_fd[i], &on_read_closure);
 | 
	
		
			
				|  |  | +      grpc_exec_ctx_flush(&exec_ctx);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    gpr_mu_unlock(mu);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* The callback should have been called by now */
 | 
	
		
			
				|  |  | +    GPR_ASSERT(fd_context.is_cb_called);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /* Drain the socket (Not really needed for the test) */
 | 
	
		
			
				|  |  |      result = read(sv[i][0], &data, 1);
 | 
	
		
			
				|  |  |      GPR_ASSERT(result == 1);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  /* Clean up */
 | 
	
		
			
				|  |  |    for (i = 0; i < 2; i++) {
 | 
	
		
			
				|  |  |      grpc_fd_orphan(&exec_ctx, em_fd[i], NULL, NULL, "");
 | 
	
		
			
				|  |  |      close(sv[i][1]);
 | 
	
		
			
				|  |  | +    free_grpc_pollset(&exec_ctx, pollset[i]);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  free_grpc_pollset(&exec_ctx, pollset);
 | 
	
		
			
				|  |  |    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -624,7 +655,8 @@ int main(int argc, char **argv) {
 | 
	
		
			
				|  |  |    grpc_pollset_init(g_pollset, &g_mu);
 | 
	
		
			
				|  |  |    test_grpc_fd();
 | 
	
		
			
				|  |  |    test_grpc_fd_change();
 | 
	
		
			
				|  |  | -  test_grpc_fd_read_notifier_pollset();
 | 
	
		
			
				|  |  | +  test_grpc_fd_read_notifier_pollset(false);
 | 
	
		
			
				|  |  | +  test_grpc_fd_read_notifier_pollset(true);
 | 
	
		
			
				|  |  |    grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
 | 
	
		
			
				|  |  |    grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
 | 
	
		
			
				|  |  |    grpc_exec_ctx_finish(&exec_ctx);
 |