Merge pull request #5957 from jtattermusch/fix_ruby_gem_building

make grpc_pollset_set_create for windows match the header
diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c
index 8077297..fa87e52 100644
--- a/src/core/iomgr/iocp_windows.c
+++ b/src/core/iomgr/iocp_windows.c
@@ -71,7 +71,8 @@
       timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
 }
 
-void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
+grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
+                                     gpr_timespec deadline) {
   BOOL success;
   DWORD bytes = 0;
   DWORD flags = 0;
@@ -84,14 +85,14 @@
       g_iocp, &bytes, &completion_key, &overlapped,
       deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
   if (success == 0 && overlapped == NULL) {
-    return;
+    return GRPC_IOCP_WORK_TIMEOUT;
   }
   GPR_ASSERT(completion_key && overlapped);
   if (overlapped == &g_iocp_custom_overlap) {
     gpr_atm_full_fetch_add(&g_custom_events, -1);
     if (completion_key == (ULONG_PTR)&g_iocp_kick_token) {
       /* We were awoken from a kick. */
-      return;
+      return GRPC_IOCP_WORK_KICK;
     }
     gpr_log(GPR_ERROR, "Unknown custom completion key.");
     abort();
@@ -121,6 +122,7 @@
   }
   gpr_mu_unlock(&socket->state_mu);
   grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
+  return GRPC_IOCP_WORK_WORK;
 }
 
 void grpc_iocp_init(void) {
@@ -140,10 +142,12 @@
 
 void grpc_iocp_flush(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_iocp_work_status work_status;
 
   do {
-    grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
-  } while (grpc_exec_ctx_flush(&exec_ctx));
+    work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
+  } while (work_status == GRPC_IOCP_WORK_KICK ||
+           grpc_exec_ctx_flush(&exec_ctx));
 }
 
 void grpc_iocp_shutdown(void) {
diff --git a/src/core/iomgr/iocp_windows.h b/src/core/iomgr/iocp_windows.h
index 75f3ba8..8b2b1ae 100644
--- a/src/core/iomgr/iocp_windows.h
+++ b/src/core/iomgr/iocp_windows.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,14 @@
 
 #include "src/core/iomgr/socket_windows.h"
 
-void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline);
+typedef enum {
+  GRPC_IOCP_WORK_WORK,
+  GRPC_IOCP_WORK_TIMEOUT,
+  GRPC_IOCP_WORK_KICK
+} grpc_iocp_work_status;
+
+grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
+                                     gpr_timespec deadline);
 void grpc_iocp_init(void);
 void grpc_iocp_kick(void);
 void grpc_iocp_flush(void);
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
index ce930b8..a4abc5b 100644
--- a/src/core/iomgr/tcp_server_windows.c
+++ b/src/core/iomgr/tcp_server_windows.c
@@ -240,8 +240,7 @@
   sp->shutting_down = 0;
   gpr_mu_lock(&sp->server->mu);
   GPR_ASSERT(sp->server->active_ports > 0);
-  if (0 == --sp->server->active_ports &&
-      sp->server->shutdown_complete != NULL) {
+  if (0 == --sp->server->active_ports) {
     notify = 1;
   }
   gpr_mu_unlock(&sp->server->mu);
diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs
index 4c742ab..282816d 100644
--- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs
@@ -32,6 +32,7 @@
 #endregion
 
 using System;
+using System.Globalization;
 using System.IO;
 using System.Reflection;
 
@@ -99,14 +100,30 @@
             // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property).
 
             var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString());
-            var fullPath = Path.Combine(GetExecutingAssemblyDirectory(),
+            var fullPath = Path.Combine(Path.GetDirectoryName(GetAssemblyPath()),
                 NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename());
             return new UnmanagedLibrary(fullPath);
         }
 
-        private static string GetExecutingAssemblyDirectory()
+        private static string GetAssemblyPath()
         {
-            return Path.GetDirectoryName(typeof(NativeExtension).GetTypeInfo().Assembly.Location);
+            var assembly = typeof(NativeExtension).GetTypeInfo().Assembly;
+
+            // If assembly is shadowed (e.g. in a webapp), EscapedCodeBase is pointing
+            // to the original location of the assembly, and Location is pointing
+            // to the shadow copy. We care about the original location because
+            // the native dlls don't get shadowed.
+            var escapedCodeBase = assembly.EscapedCodeBase;
+            if (IsFileUri(escapedCodeBase))
+            {
+                return new Uri(escapedCodeBase).LocalPath;
+            }
+            return assembly.Location;
+        }
+
+        private static bool IsFileUri(string uri)
+        {
+            return uri.ToLowerInvariant().StartsWith(Uri.UriSchemeFile);
         }
 
         private static string GetPlatformString()
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index af05ddf..cd0aa6a 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -72,6 +72,10 @@
  * the flags used to create metadata from a Hash */
 static ID id_flags;
 
+/* id_credentials is the name of the hidden ivar that preserves the value
+ * of the credentials added to the call */
+static ID id_credentials;
+
 /* id_input_md is the name of the hidden ivar that preserves the hash used to
  * create metadata, so that references to the strings it contains last as long
  * as the call the metadata is added to. */
@@ -299,6 +303,7 @@
              "grpc_call_set_credentials failed with %s (code=%d)",
              grpc_call_error_detail_of(err), err);
   }
+  rb_ivar_set(self, id_credentials, credentials);
   return Qnil;
 }
 
@@ -859,6 +864,7 @@
   id_cq = rb_intern("__cq");
   id_flags = rb_intern("__flags");
   id_input_md = rb_intern("__input_md");
+  id_credentials = rb_intern("__credentials");
 
   /* Ids used in constructing the batch result. */
   sym_send_message = ID2SYM(rb_intern("send_message"));
diff --git a/src/ruby/ext/grpc/rb_call_credentials.c b/src/ruby/ext/grpc/rb_call_credentials.c
index 2426f10..7c4b69f 100644
--- a/src/ruby/ext/grpc/rb_call_credentials.c
+++ b/src/ruby/ext/grpc/rb_call_credentials.c
@@ -50,9 +50,9 @@
  * grpc_call_credentials */
 static VALUE grpc_rb_cCallCredentials = Qnil;
 
-/* grpc_rb_call_credentials wraps a grpc_call_credentials. It provides a peer
- * ruby object, 'mark' to minimize copying when a credential is created from
- * ruby. */
+/* grpc_rb_call_credentials wraps a grpc_call_credentials. It provides a mark
+ * object that is used to hold references to any objects used to create the
+ * credentials. */
 typedef struct grpc_rb_call_credentials {
   /* Holder of ruby objects involved in contructing the credentials */
   VALUE mark;
@@ -146,13 +146,8 @@
     return;
   }
   wrapper = (grpc_rb_call_credentials *)p;
-
-  /* Delete the wrapped object if the mark object is Qnil, which indicates that
-   * no other object is the actual owner. */
-  if (wrapper->wrapped != NULL && wrapper->mark == Qnil) {
-    grpc_call_credentials_release(wrapper->wrapped);
-    wrapper->wrapped = NULL;
-  }
+  grpc_call_credentials_release(wrapper->wrapped);
+  wrapper->wrapped = NULL;
 
   xfree(p);
 }
@@ -164,8 +159,6 @@
     return;
   }
   wrapper = (grpc_rb_call_credentials *)p;
-
-  /* If it's not already cleaned up, mark the mark object */
   if (wrapper->mark != Qnil) {
     rb_gc_mark(wrapper->mark);
   }
@@ -194,7 +187,7 @@
 /* Creates a wrapping object for a given call credentials. This should only be
  * called with grpc_call_credentials objects that are not already associated
  * with any Ruby object */
-VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c) {
+VALUE grpc_rb_wrap_call_credentials(grpc_call_credentials *c, VALUE mark) {
   VALUE rb_wrapper;
   grpc_rb_call_credentials *wrapper;
   if (c == NULL) {
@@ -204,6 +197,7 @@
   TypedData_Get_Struct(rb_wrapper, grpc_rb_call_credentials,
                        &grpc_rb_call_credentials_data_type, wrapper);
   wrapper->wrapped = c;
+  wrapper->mark = mark;
   return rb_wrapper;
 }
 
@@ -267,6 +261,7 @@
     return Qnil;
   }
 
+  wrapper->mark = proc;
   wrapper->wrapped = creds;
   rb_ivar_set(self, id_callback, proc);
 
@@ -277,15 +272,18 @@
                                               VALUE self) {
   grpc_call_credentials *creds;
   grpc_call_credentials *other;
+  VALUE mark;
   if (argc == 0) {
     return self;
   }
+  mark = rb_ary_new();
   creds = grpc_rb_get_wrapped_call_credentials(self);
   for (int i = 0; i < argc; i++) {
+    rb_ary_push(mark, argv[i]);
     other = grpc_rb_get_wrapped_call_credentials(argv[i]);
     creds = grpc_composite_call_credentials_create(creds, other, NULL);
   }
-  return grpc_rb_wrap_call_credentials(creds);
+  return grpc_rb_wrap_call_credentials(creds, mark);
 }
 
 void Init_grpc_call_credentials() {
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 0e6badb..e1aaa53 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -70,11 +70,10 @@
 /* Used during the conversion of a hash to channel args during channel setup */
 static VALUE grpc_rb_cChannelArgs;
 
-/* grpc_rb_channel wraps a grpc_channel.  It provides a peer ruby object,
- * 'mark' to minimize copying when a channel is created from ruby. */
+/* grpc_rb_channel wraps a grpc_channel. */
 typedef struct grpc_rb_channel {
-  /* Holder of ruby objects involved in constructing the channel */
-  VALUE mark;
+  VALUE credentials;
+
   /* The actual channel */
   grpc_channel *wrapped;
 } grpc_rb_channel;
@@ -87,13 +86,8 @@
   };
   ch = (grpc_rb_channel *)p;
 
-  /* Deletes the wrapped object if the mark object is Qnil, which indicates
-   * that no other object is the actual owner. */
-  if (ch->wrapped != NULL && ch->mark == Qnil) {
+  if (ch->wrapped != NULL) {
     grpc_channel_destroy(ch->wrapped);
-    rb_warning("channel gc: destroyed the c channel");
-  } else {
-    rb_warning("channel gc: did not destroy the c channel");
   }
 
   xfree(p);
@@ -106,8 +100,8 @@
     return;
   }
   channel = (grpc_rb_channel *)p;
-  if (channel->mark != Qnil) {
-    rb_gc_mark(channel->mark);
+  if (channel->credentials != Qnil) {
+    rb_gc_mark(channel->credentials);
   }
 }
 
@@ -125,7 +119,7 @@
 static VALUE grpc_rb_channel_alloc(VALUE cls) {
   grpc_rb_channel *wrapper = ALLOC(grpc_rb_channel);
   wrapper->wrapped = NULL;
-  wrapper->mark = Qnil;
+  wrapper->credentials = Qnil;
   return TypedData_Wrap_Struct(cls, &grpc_channel_data_type, wrapper);
 }
 
@@ -162,6 +156,7 @@
     }
     ch = grpc_insecure_channel_create(target_chars, &args, NULL);
   } else {
+    wrapper->credentials = credentials;
     creds = grpc_rb_get_wrapped_channel_credentials(credentials);
     ch = grpc_secure_channel_create(creds, target_chars, &args, NULL);
   }
@@ -330,7 +325,6 @@
   if (ch != NULL) {
     grpc_channel_destroy(ch);
     wrapper->wrapped = NULL;
-    wrapper->mark = Qnil;
   }
 
   return Qnil;
diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c
index 8c6fc3b..f649084 100644
--- a/src/ruby/ext/grpc/rb_channel_credentials.c
+++ b/src/ruby/ext/grpc/rb_channel_credentials.c
@@ -49,8 +49,8 @@
 static VALUE grpc_rb_cChannelCredentials = Qnil;
 
 /* grpc_rb_channel_credentials wraps a grpc_channel_credentials.  It provides a
- * peer ruby object, 'mark' to minimize copying when a credential is
- * created from ruby. */
+ * mark object that is used to hold references to any objects used to create
+ * the credentials. */
 typedef struct grpc_rb_channel_credentials {
   /* Holder of ruby objects involved in constructing the credentials */
   VALUE mark;
@@ -66,13 +66,8 @@
     return;
   };
   wrapper = (grpc_rb_channel_credentials *)p;
-
-  /* Delete the wrapped object if the mark object is Qnil, which indicates that
-   * no other object is the actual owner. */
-  if (wrapper->wrapped != NULL && wrapper->mark == Qnil) {
-    grpc_channel_credentials_release(wrapper->wrapped);
-    wrapper->wrapped = NULL;
-  }
+  grpc_channel_credentials_release(wrapper->wrapped);
+  wrapper->wrapped = NULL;
 
   xfree(p);
 }
@@ -85,7 +80,6 @@
   }
   wrapper = (grpc_rb_channel_credentials *)p;
 
-  /* If it's not already cleaned up, mark the mark object */
   if (wrapper->mark != Qnil) {
     rb_gc_mark(wrapper->mark);
   }
@@ -114,7 +108,7 @@
 /* Creates a wrapping object for a given channel credentials. This should only
  * be called with grpc_channel_credentials objects that are not already
  * associated with any Ruby object. */
-VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c) {
+VALUE grpc_rb_wrap_channel_credentials(grpc_channel_credentials *c, VALUE mark) {
   VALUE rb_wrapper;
   grpc_rb_channel_credentials *wrapper;
   if (c == NULL) {
@@ -124,6 +118,7 @@
   TypedData_Get_Struct(rb_wrapper, grpc_rb_channel_credentials,
                        &grpc_rb_channel_credentials_data_type, wrapper);
   wrapper->wrapped = c;
+  wrapper->mark = mark;
   return rb_wrapper;
 }
 
@@ -222,11 +217,15 @@
                                                  VALUE self) {
   grpc_channel_credentials *creds;
   grpc_call_credentials *other;
+  VALUE mark;
   if (argc == 0) {
     return self;
   }
+  mark = rb_ary_new();
+  rb_ary_push(mark, self);
   creds = grpc_rb_get_wrapped_channel_credentials(self);
   for (int i = 0; i < argc; i++) {
+    rb_ary_push(mark, argv[i]);
     other = grpc_rb_get_wrapped_call_credentials(argv[i]);
     creds = grpc_composite_channel_credentials_create(creds, other, NULL);
     if (creds == NULL) {
@@ -234,7 +233,7 @@
                "Failed to compose channel and call credentials");
     }
   }
-  return grpc_rb_wrap_channel_credentials(creds);
+  return grpc_rb_wrap_channel_credentials(creds, mark);
 }
 
 void Init_grpc_channel_credentials() {
diff --git a/tools/run_tests/build_artifact_python.sh b/tools/run_tests/build_artifact_python.sh
index 7ba04d7..1f23f9f 100755
--- a/tools/run_tests/build_artifact_python.sh
+++ b/tools/run_tests/build_artifact_python.sh
@@ -35,15 +35,18 @@
 if [ "$SKIP_PIP_INSTALL" == "" ]
 then
   pip install --upgrade six
-  pip install --upgrade setuptools
+  # There's a bug in newer versions of setuptools (see
+  # https://bitbucket.org/pypa/setuptools/issues/503/pkg_resources_vendorpackagingrequirementsi)
+  pip install --upgrade 'setuptools==18'
   pip install -rrequirements.txt
 fi
 
+export GRPC_PYTHON_USE_CUSTOM_BDIST=0
+export GRPC_PYTHON_BUILD_WITH_CYTHON=1
+
 # Build the source distribution first because MANIFEST.in cannot override
 # exclusion of built shared objects among package resources (for some
 # inexplicable reason).
-GRPC_PYTHON_USE_CUSTOM_BDIST=0  \
-GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
 ${SETARCH_CMD} python setup.py  \
     sdist
 
@@ -51,15 +54,11 @@
 # and thus ought to be run in a shell command separate of others. Further, it
 # trashes the actual bdist_wheel output, so it should be run first so that
 # bdist_wheel may be run unmolested.
-GRPC_PYTHON_USE_CUSTOM_BDIST=0  \
-GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
 ${SETARCH_CMD} python setup.py  \
     build_tagged_ext
 
 # Wheel has a bug where directories don't get excluded.
 # https://bitbucket.org/pypa/wheel/issues/99/cannot-exclude-directory
-GRPC_PYTHON_USE_CUSTOM_BDIST=0  \
-GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
 ${SETARCH_CMD} python setup.py  \
     bdist_wheel