aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <craig.tiller@gmail.com>2015-05-15 14:44:42 -0700
committerGravatar Craig Tiller <craig.tiller@gmail.com>2015-05-15 14:44:42 -0700
commit4caf6302b80b09eec427440c24e52744493a906e (patch)
tree4ab612fc7247cb4f9f3dd0816bb3ae7ceaa4ac4a
parent069daa383e720ac662fd4d8dd852f486556dcacf (diff)
parent9aaa1b61e7bd6a1173d6d7fb4b68ca8ae74bcabe (diff)
Merge github.com:grpc/grpc into mmm-mmm-mmm-mmm
-rw-r--r--BUILD1
-rw-r--r--Makefile1
-rw-r--r--build.json3
-rw-r--r--include/grpc/support/tls_pthread.h6
-rw-r--r--src/core/support/tls_pthread.c45
-rw-r--r--src/node/interop/interop_client.js14
-rw-r--r--src/node/test/interop_sanity_test.js4
-rw-r--r--src/php/ext/grpc/call.c17
-rw-r--r--src/php/ext/grpc/call.h4
-rw-r--r--src/php/ext/grpc/completion_queue.c50
-rw-r--r--src/php/ext/grpc/completion_queue.h50
-rwxr-xr-xsrc/php/ext/grpc/config.m42
-rw-r--r--src/php/ext/grpc/php_grpc.c3
-rw-r--r--src/php/ext/grpc/server.c19
-rwxr-xr-xsrc/php/ext/grpc/server.h1
-rw-r--r--tools/dockerfile/grpc_java_android/Dockerfile66
-rw-r--r--tools/dockerfile/grpc_java_android/README.md42
-rw-r--r--vsprojects/gpr/gpr.vcxproj2
-rw-r--r--vsprojects/gpr/gpr.vcxproj.filters3
19 files changed, 298 insertions, 35 deletions
diff --git a/BUILD b/BUILD
index 7bbbe2fbf9..72da642bde 100644
--- a/BUILD
+++ b/BUILD
@@ -84,6 +84,7 @@ cc_library(
"src/core/support/time.c",
"src/core/support/time_posix.c",
"src/core/support/time_win32.c",
+ "src/core/support/tls_pthread.c",
],
hdrs = [
"include/grpc/support/alloc.h",
diff --git a/Makefile b/Makefile
index 6d47993f8d..db5d3f6bca 100644
--- a/Makefile
+++ b/Makefile
@@ -2327,6 +2327,7 @@ LIBGPR_SRC = \
src/core/support/time.c \
src/core/support/time_posix.c \
src/core/support/time_win32.c \
+ src/core/support/tls_pthread.c \
PUBLIC_HEADERS_C += \
include/grpc/support/alloc.h \
diff --git a/build.json b/build.json
index b087031bfc..166e21a106 100644
--- a/build.json
+++ b/build.json
@@ -372,7 +372,8 @@
"src/core/support/thd_win32.c",
"src/core/support/time.c",
"src/core/support/time_posix.c",
- "src/core/support/time_win32.c"
+ "src/core/support/time_win32.c",
+ "src/core/support/tls_pthread.c"
],
"secure": "no",
"vs_project_guid": "{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}"
diff --git a/include/grpc/support/tls_pthread.h b/include/grpc/support/tls_pthread.h
index 07eb12e5bf..67f169dd7d 100644
--- a/include/grpc/support/tls_pthread.h
+++ b/include/grpc/support/tls_pthread.h
@@ -34,6 +34,9 @@
#ifndef GRPC_SUPPORT_TLS_PTHREAD_H
#define GRPC_SUPPORT_TLS_PTHREAD_H
+#include <grpc/support/log.h> /* for GPR_ASSERT */
+#include <pthread.h>
+
/* Thread local storage based on pthread library calls.
#include tls.h to use this - and see that file for documentation */
@@ -46,8 +49,7 @@ struct gpr_pthread_thread_local {
#define gpr_tls_init(tls) GPR_ASSERT(0 == pthread_key_create(&(tls)->key, NULL))
#define gpr_tls_destroy(tls) pthread_key_delete((tls)->key)
-#define gpr_tls_set(tls, new_value) \
- (GPR_ASSERT(pthread_setspecific((tls)->key, (void*)(new_value)) == 0), (new_value))
+gpr_intptr gpr_tls_set(struct gpr_pthread_thread_local *tls, gpr_intptr value);
#define gpr_tls_get(tls) ((gpr_intptr)pthread_getspecific((tls)->key))
#endif
diff --git a/src/core/support/tls_pthread.c b/src/core/support/tls_pthread.c
new file mode 100644
index 0000000000..f2e76a553f
--- /dev/null
+++ b/src/core/support/tls_pthread.c
@@ -0,0 +1,45 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_PTHREAD_TLS
+
+#include <grpc/support/tls.h>
+
+gpr_intptr gpr_tls_set(struct gpr_pthread_thread_local *tls, gpr_intptr value) {
+ GPR_ASSERT(0 == pthread_setspecific(tls->key, (void*)value));
+ return value;
+}
+
+#endif /* GPR_PTHREAD_TLS */
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 402843162e..80f811901c 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -263,6 +263,19 @@ function cancelAfterFirstResponse(client, done) {
});
}
+function timeoutOnSleepingServer(client, done) {
+ var deadline = new Date();
+ deadline.setMilliseconds(deadline.getMilliseconds() + 1);
+ var call = client.fullDuplexCall(null, deadline);
+ call.write({
+ payload: {body: zeroBuffer(27182)}
+ });
+ call.on('error', function(error) {
+ assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED);
+ done();
+ });
+}
+
/**
* Run one of the authentication tests.
* @param {string} expected_user The expected username in the response
@@ -315,6 +328,7 @@ var test_cases = {
empty_stream: emptyStream,
cancel_after_begin: cancelAfterBegin,
cancel_after_first_response: cancelAfterFirstResponse,
+ timeout_on_sleeping_server: timeoutOnSleepingServer,
compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER, null),
service_account_creds: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
jwt_token_creds: _.partial(authTest, AUTH_USER, null)
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index 6b3aa3dd84..fcd8eb6403 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -86,4 +86,8 @@ describe('Interop tests', function() {
interop_client.runTest(port, name_override, 'cancel_after_first_response',
true, true, done);
});
+ it('should pass timeout_on_sleeping_server', function(done) {
+ interop_client.runTest(port, name_override, 'timeout_on_sleeping_server',
+ true, true, done);
+ });
});
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 9cc4fd7f39..9f651ff56f 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -52,6 +52,7 @@
#include <grpc/support/alloc.h>
#include <grpc/grpc.h>
+#include "completion_queue.h"
#include "timeval.h"
#include "channel.h"
#include "byte_buffer.h"
@@ -62,13 +63,6 @@ zend_class_entry *grpc_ce_call;
void free_wrapped_grpc_call(void *object TSRMLS_DC) {
wrapped_grpc_call *call = (wrapped_grpc_call *)object;
if (call->owned && call->wrapped != NULL) {
- if (call->queue != NULL) {
- grpc_completion_queue_shutdown(call->queue);
- while (grpc_completion_queue_next(call->queue, gpr_inf_future).type !=
- GRPC_QUEUE_SHUTDOWN)
- ;
- grpc_completion_queue_destroy(call->queue);
- }
grpc_call_destroy(call->wrapped);
}
efree(call);
@@ -95,15 +89,13 @@ zend_object_value create_wrapped_grpc_call(zend_class_entry *class_type
/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the struct
should be destroyed at the end of the object's lifecycle */
-zval *grpc_php_wrap_call(grpc_call *wrapped, grpc_completion_queue *queue,
- bool owned) {
+zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned) {
zval *call_object;
MAKE_STD_ZVAL(call_object);
object_init_ex(call_object, grpc_ce_call);
wrapped_grpc_call *call =
(wrapped_grpc_call *)zend_object_store_get_object(call_object TSRMLS_CC);
call->wrapped = wrapped;
- call->queue = queue;
return call_object;
}
@@ -247,9 +239,8 @@ PHP_METHOD(Call, __construct) {
wrapped_grpc_timeval *deadline =
(wrapped_grpc_timeval *)zend_object_store_get_object(
deadline_obj TSRMLS_CC);
- call->queue = grpc_completion_queue_create();
call->wrapped = grpc_channel_create_call(
- channel->wrapped, call->queue, method, channel->target,
+ channel->wrapped, completion_queue, method, channel->target,
deadline->wrapped);
}
@@ -415,7 +406,7 @@ PHP_METHOD(Call, startBatch) {
(long)error TSRMLS_CC);
goto cleanup;
}
- event = grpc_completion_queue_pluck(call->queue, call->wrapped,
+ event = grpc_completion_queue_pluck(completion_queue, call->wrapped,
gpr_inf_future);
if (!event.success) {
zend_throw_exception(spl_ce_LogicException,
diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h
index e7eb9a75e2..f3ef89dc97 100644
--- a/src/php/ext/grpc/call.h
+++ b/src/php/ext/grpc/call.h
@@ -54,15 +54,13 @@ typedef struct wrapped_grpc_call {
bool owned;
grpc_call *wrapped;
- grpc_completion_queue *queue;
} wrapped_grpc_call;
/* Initializes the Call PHP class */
void grpc_init_call(TSRMLS_D);
/* Creates a Call object that wraps the given grpc_call struct */
-zval *grpc_php_wrap_call(grpc_call *wrapped, grpc_completion_queue *queue,
- bool owned);
+zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned);
/* Creates and returns a PHP associative array of metadata from a C array of
* call metadata */
diff --git a/src/php/ext/grpc/completion_queue.c b/src/php/ext/grpc/completion_queue.c
new file mode 100644
index 0000000000..b24c83757c
--- /dev/null
+++ b/src/php/ext/grpc/completion_queue.c
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "completion_queue.h"
+
+#include <php.h>
+
+grpc_completion_queue *completion_queue;
+
+void grpc_php_init_completion_queue(TSRMLS_D) {
+ completion_queue = grpc_completion_queue_create();
+}
+
+void grpc_php_shutdown_completion_queue(TSRMLS_D) {
+ grpc_completion_queue_shutdown(completion_queue);
+ while (grpc_completion_queue_next(completion_queue, gpr_inf_future).type !=
+ GRPC_QUEUE_SHUTDOWN)
+ ;
+ grpc_completion_queue_destroy(completion_queue);
+}
diff --git a/src/php/ext/grpc/completion_queue.h b/src/php/ext/grpc/completion_queue.h
new file mode 100644
index 0000000000..d5dac4f0cf
--- /dev/null
+++ b/src/php/ext/grpc/completion_queue.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_PHP_GRPC_COMPLETION_QUEUE_H_
+#define GRPC_PHP_GRPC_COMPLETION_QUEUE_H_
+
+#include <php.h>
+
+#include <grpc/grpc.h>
+
+/* The global completion queue for all operations */
+extern grpc_completion_queue *completion_queue;
+
+/* Initializes the completion queue */
+void grpc_php_init_completion_queue(TSRMLS_D);
+
+/* Shut down the completion queue */
+void grpc_php_shutdown_completion_queue(TSRMLS_D);
+
+#endif /* GRPC_PHP_GRPC_COMPLETION_QUEUE_H_ */
diff --git a/src/php/ext/grpc/config.m4 b/src/php/ext/grpc/config.m4
index 11778e3bb6..b485aabf40 100755
--- a/src/php/ext/grpc/config.m4
+++ b/src/php/ext/grpc/config.m4
@@ -66,5 +66,5 @@ if test "$PHP_GRPC" != "no"; then
PHP_SUBST(GRPC_SHARED_LIBADD)
- PHP_NEW_EXTENSION(grpc, byte_buffer.c call.c channel.c credentials.c timeval.c server.c server_credentials.c php_grpc.c, $ext_shared, , -Wall -Werror -std=c11)
+ PHP_NEW_EXTENSION(grpc, byte_buffer.c call.c channel.c completion_queue.c credentials.c timeval.c server.c server_credentials.c php_grpc.c, $ext_shared, , -Wall -Werror -std=c11)
fi
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index 3e669ecd17..fedcf0f539 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -37,6 +37,7 @@
#include "timeval.h"
#include "credentials.h"
#include "server_credentials.h"
+#include "completion_queue.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -188,6 +189,7 @@ PHP_MINIT_FUNCTION(grpc) {
grpc_init_timeval(TSRMLS_C);
grpc_init_credentials(TSRMLS_C);
grpc_init_server_credentials(TSRMLS_C);
+ grpc_php_init_completion_queue(TSRMLS_C);
return SUCCESS;
}
/* }}} */
@@ -199,6 +201,7 @@ PHP_MSHUTDOWN_FUNCTION(grpc) {
UNREGISTER_INI_ENTRIES();
*/
grpc_shutdown_timeval(TSRMLS_C);
+ grpc_php_shutdown_completion_queue(TSRMLS_C);
grpc_shutdown();
return SUCCESS;
}
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index c2e00b16f4..b7995b6b8b 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -51,6 +51,7 @@
#include <grpc/support/log.h>
#include <grpc/grpc_security.h>
+#include "completion_queue.h"
#include "server.h"
#include "channel.h"
#include "server_credentials.h"
@@ -61,13 +62,6 @@ zend_class_entry *grpc_ce_server;
/* Frees and destroys an instance of wrapped_grpc_server */
void free_wrapped_grpc_server(void *object TSRMLS_DC) {
wrapped_grpc_server *server = (wrapped_grpc_server *)object;
- if (server->queue != NULL) {
- grpc_completion_queue_shutdown(server->queue);
- while (grpc_completion_queue_next(server->queue, gpr_inf_future).type !=
- GRPC_QUEUE_SHUTDOWN)
- ;
- grpc_completion_queue_destroy(server->queue);
- }
if (server->wrapped != NULL) {
grpc_server_shutdown(server->wrapped);
grpc_server_destroy(server->wrapped);
@@ -96,7 +90,6 @@ zend_object_value create_wrapped_grpc_server(zend_class_entry *class_type
/**
* Constructs a new instance of the Server class
- * @param CompletionQueue $queue The completion queue to use with the server
* @param array $args The arguments to pass to the server (optional)
*/
PHP_METHOD(Server, __construct) {
@@ -112,7 +105,6 @@ PHP_METHOD(Server, __construct) {
1 TSRMLS_CC);
return;
}
- server->queue = grpc_completion_queue_create();
if (args_array == NULL) {
server->wrapped = grpc_server_create(NULL);
} else {
@@ -120,7 +112,7 @@ PHP_METHOD(Server, __construct) {
server->wrapped = grpc_server_create(&args);
efree(args.args);
}
- grpc_server_register_completion_queue(server->wrapped, server->queue);
+ grpc_server_register_completion_queue(server->wrapped, completion_queue);
}
/**
@@ -144,21 +136,20 @@ PHP_METHOD(Server, requestCall) {
grpc_metadata_array_init(&metadata);
error_code =
grpc_server_request_call(server->wrapped, &call, &details, &metadata,
- server->queue, server->queue, NULL);
+ completion_queue, completion_queue, NULL);
if (error_code != GRPC_CALL_OK) {
zend_throw_exception(spl_ce_LogicException, "request_call failed",
(long)error_code TSRMLS_CC);
goto cleanup;
}
- event = grpc_completion_queue_pluck(server->queue, NULL, gpr_inf_future);
+ event = grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future);
if (!event.success) {
zend_throw_exception(spl_ce_LogicException,
"Failed to request a call for some reason",
1 TSRMLS_CC);
goto cleanup;
}
- add_property_zval(result, "call", grpc_php_wrap_call(call, server->queue,
- true));
+ add_property_zval(result, "call", grpc_php_wrap_call(call, true));
add_property_string(result, "method", details.method, true);
add_property_string(result, "host", details.host, true);
add_property_zval(result, "absolute_deadline",
diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h
index a2ee2ff5a9..022257f37c 100755
--- a/src/php/ext/grpc/server.h
+++ b/src/php/ext/grpc/server.h
@@ -53,7 +53,6 @@ typedef struct wrapped_grpc_server {
zend_object std;
grpc_server *wrapped;
- grpc_completion_queue *queue;
} wrapped_grpc_server;
/* Initializes the Server class */
diff --git a/tools/dockerfile/grpc_java_android/Dockerfile b/tools/dockerfile/grpc_java_android/Dockerfile
new file mode 100644
index 0000000000..d11e88943c
--- /dev/null
+++ b/tools/dockerfile/grpc_java_android/Dockerfile
@@ -0,0 +1,66 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Dockerfile for the gRPC Java dev image
+FROM grpc/java_base
+
+# Required by accessing Android's aapt
+RUN apt-get install -y lib32stdc++6 lib32z1 && apt-get clean
+
+# Install Android SDK 24.2
+RUN curl -L http://dl.google.com/android/android-sdk_r24.2-linux.tgz | tar xz -C /usr/local
+
+# Environment variables
+ENV ANDROID_HOME /usr/local/android-sdk-linux
+ENV PATH $PATH:$ANDROID_HOME/tools
+ENV PATH $PATH:$ANDROID_HOME/platform-tools
+# Some old Docker versions consider '/' as HOME
+ENV HOME /root
+
+# Update sdk for android 5.1 (API level 22)
+RUN echo y | android update sdk --all --filter platform-tools,build-tools-22.0.1,sys-img-armeabi-v7a-android-22,android-22,extra-android-m2repository,extra-google-m2repository --no-ui --force
+
+# Create an AVD with API level 22
+RUN echo no | android create avd --force -n avd-api-22 -t android-22
+
+# Pull gRPC Java and trigger download of needed Maven and Gradle artifacts.
+RUN git clone --depth 1 https://github.com/grpc/grpc-java.git /var/local/git/grpc-java && \
+ cd /var/local/git/grpc-java && \
+ ./gradlew grpc-core:install grpc-stub:install grpc-okhttp:install grpc-protobuf-nano:install && \
+ rm -r "$(pwd)"
+
+# Pull gRPC Android integration test App
+RUN git clone --depth 1 https://github.com/madongfly/grpc-android-test.git /var/local/git/grpc-android-test
+
+# Config android sdk for gradle
+RUN cd /var/local/git/grpc-android-test && echo "sdk.dir=/usr/local/android-sdk-linux" > local.properties
+
+# Build apks to trigger download of needed Maven and Gradle artifacts.
+RUN cd /var/local/git/grpc-android-test && ./gradlew assembleDebug
+RUN cd /var/local/git/grpc-android-test && ./gradlew assembleDebugAndroidTest
diff --git a/tools/dockerfile/grpc_java_android/README.md b/tools/dockerfile/grpc_java_android/README.md
new file mode 100644
index 0000000000..b4c9645e6a
--- /dev/null
+++ b/tools/dockerfile/grpc_java_android/README.md
@@ -0,0 +1,42 @@
+GRPC Android Dockerfile
+====================
+
+Dockerfile for creating the gRPC Android integration test image
+
+As of 2015/05 this
+ - is based on the gRPC Java base
+ - installs Android sdk 24.2
+ - creates an AVD for API level 22
+ - Pulls gRpc Android test App from github
+
+Usage
+-----
+
+Start the emulator in a detached container, the argument is the name of the AVD you want to start:
+
+```
+$ sudo docker run --name=grpc_android_test -d grpc/android /var/local/git/grpc-android-test/start-emulator.sh avd-api-22
+```
+
+You can use the following cammand to wait until the emulator is ready:
+```
+$ sudo docker exec grpc_android_test /var/local/git/grpc-android-test/wait-for-emulator.sh
+```
+
+When you want to update the apk, run:
+```
+$ sudo docker exec grpc_android_test /var/local/git/grpc-android-test/update-apk.sh
+```
+It will pull the fresh code of gRpc Java and our integration test app from github, build and install it to the runing emulator (so you need to make sure there is a runing emulator).
+
+Trigger the integration test:
+```
+$ sudo docker exec grpc_android_test /var/local/git/grpc-android-test/run-test.sh -e server_host <hostname or ip address> -e server_port 8030 -e server_host_override foo.test.google.fr -e use_tls true -e use_test_ca true
+```
+
+You can also use the android/adb cammands to get more info, such as:
+```
+$ sudo docker exec grpc_android_test android list avd
+$ sudo docker exec grpc_android_test adb devices
+$ sudo docker exec grpc_android_test adb logcat
+```
diff --git a/vsprojects/gpr/gpr.vcxproj b/vsprojects/gpr/gpr.vcxproj
index dd1201be5c..a7e7c2754f 100644
--- a/vsprojects/gpr/gpr.vcxproj
+++ b/vsprojects/gpr/gpr.vcxproj
@@ -255,6 +255,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\support\time_win32.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\support\tls_pthread.c">
+ </ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/vsprojects/gpr/gpr.vcxproj.filters b/vsprojects/gpr/gpr.vcxproj.filters
index 7d4fd01141..0f81ef598a 100644
--- a/vsprojects/gpr/gpr.vcxproj.filters
+++ b/vsprojects/gpr/gpr.vcxproj.filters
@@ -109,6 +109,9 @@
<ClCompile Include="..\..\src\core\support\time_win32.c">
<Filter>src\core\support</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\support\tls_pthread.c">
+ <Filter>src\core\support</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\grpc\support\alloc.h">