Merge pull request #9888 from murgatroid99/electron_uv_fix

Fix missing wakeups when using the libuv iomgr under Electron
diff --git a/binding.gyp b/binding.gyp
index b8a1a52..6fbe59b 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -54,10 +54,8 @@
       'GPR_BACKWARDS_COMPATIBILITY_MODE'
     ],
     'conditions': [
-      ['runtime=="node" and grpc_uv=="true"', {
+      ['grpc_uv=="true"', {
         'defines': [
-          # Disabling this while bugs are ironed out. Uncomment this to
-          # re-enable libuv integration in C core.
           'GRPC_UV'
         ]
       }],
diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c
index a379ddf..af33949 100644
--- a/src/core/lib/iomgr/pollset_uv.c
+++ b/src/core/lib/iomgr/pollset_uv.c
@@ -57,14 +57,28 @@
 
 gpr_mu grpc_polling_mu;
 
+/* This is used solely to kick the uv loop, by setting a callback to be run
+   immediately in the next loop iteration.
+   Note: In the future, if there is a bug that involves missing wakeups in the
+   future, try adding a uv_async_t to kick the loop differently */
+uv_timer_t dummy_uv_handle;
+
 size_t grpc_pollset_size() { return sizeof(grpc_pollset); }
 
+void dummy_timer_cb(uv_timer_t *handle) {}
+
 void grpc_pollset_global_init(void) {
   gpr_mu_init(&grpc_polling_mu);
+  uv_timer_init(uv_default_loop(), &dummy_uv_handle);
   grpc_pollset_work_run_loop = 1;
 }
 
-void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); }
+static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; }
+
+void grpc_pollset_global_shutdown(void) {
+  gpr_mu_destroy(&grpc_polling_mu);
+  uv_close((uv_handle_t *)&dummy_uv_handle, timer_close_cb);
+}
 
 void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
   *mu = &grpc_polling_mu;
@@ -72,8 +86,6 @@
   pollset->shutting_down = 0;
 }
 
-static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; }
-
 void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                            grpc_closure *closure) {
   GPR_ASSERT(!pollset->shutting_down);
@@ -81,6 +93,9 @@
   if (grpc_pollset_work_run_loop) {
     // Drain any pending UV callbacks without blocking
     uv_run(uv_default_loop(), UV_RUN_NOWAIT);
+  } else {
+    // kick the loop once
+    uv_timer_start(&dummy_uv_handle, dummy_timer_cb, 0, 0);
   }
   grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
 }
@@ -130,6 +145,7 @@
 
 grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
                               grpc_pollset_worker *specific_worker) {
+  uv_timer_start(&dummy_uv_handle, dummy_timer_cb, 0, 0);
   return GRPC_ERROR_NONE;
 }
 
diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template
index 9d7034e..2290411 100644
--- a/templates/binding.gyp.template
+++ b/templates/binding.gyp.template
@@ -56,10 +56,8 @@
         'GPR_BACKWARDS_COMPATIBILITY_MODE'
       ],
       'conditions': [
-        ['runtime=="node" and grpc_uv=="true"', {
+        ['grpc_uv=="true"', {
           'defines': [
-            # Disabling this while bugs are ironed out. Uncomment this to
-            # re-enable libuv integration in C core.
             'GRPC_UV'
           ]
         }],