aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--INSTALL217
-rw-r--r--INSTALL.md46
-rw-r--r--README.md2
-rw-r--r--doc/interop-test-descriptions.md5
-rw-r--r--examples/README.md2
-rw-r--r--examples/cpp/README.md17
-rw-r--r--examples/cpp/cpptutorial.md2
-rw-r--r--examples/cpp/helloworld/README.md2
-rw-r--r--examples/node/README.md2
-rw-r--r--grpc.def1
-rw-r--r--include/grpc/impl/codegen/sync.h4
-rw-r--r--src/core/channel/client_channel.c2
-rw-r--r--src/core/channel/client_uchannel.c2
-rw-r--r--src/core/channel/subchannel_call_holder.c18
-rw-r--r--src/core/iomgr/iomgr.c16
-rw-r--r--src/core/iomgr/iomgr_internal.h6
-rw-r--r--src/core/iomgr/pollset_multipoller_with_poll_posix.c7
-rw-r--r--src/core/support/sync.c7
-rw-r--r--src/core/surface/server.c14
-rw-r--r--src/core/transport/chttp2/internal.h21
-rw-r--r--src/core/transport/chttp2/parsing.c6
-rw-r--r--src/core/transport/chttp2/stream_lists.c38
-rw-r--r--src/core/transport/chttp2/writing.c37
-rw-r--r--src/core/transport/chttp2_transport.c95
-rw-r--r--src/core/transport/metadata.c8
-rw-r--r--src/core/transport/transport.c2
-rw-r--r--src/core/transport/transport.h12
-rw-r--r--src/node/interop/interop_client.js3
-rw-r--r--src/node/src/client.js114
-rw-r--r--src/node/test/surface_test.js8
-rw-r--r--src/objective-c/GRPCClient/private/GRPCCompletionQueue.h2
-rw-r--r--src/objective-c/GRPCClient/private/GRPCCompletionQueue.m2
-rw-r--r--src/python/grpcio/grpc/_cython/imports.generated.c2
-rw-r--r--src/python/grpcio/grpc/_cython/imports.generated.h3
-rw-r--r--src/python/grpcio/tests/_runner.py11
-rw-r--r--src/python/grpcio/tests/tests.json62
-rw-r--r--src/python/grpcio/tests/unit/_sanity/__init__.py30
-rw-r--r--src/python/grpcio/tests/unit/_sanity/_sanity_test.py53
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c2
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h3
-rw-r--r--test/cpp/interop/reconnect_interop_client.cc4
-rw-r--r--test/cpp/interop/reconnect_interop_server.cc2
-rw-r--r--tools/README.md4
-rw-r--r--tools/run_tests/build_node.bat14
-rwxr-xr-xtools/run_tests/build_python.sh3
-rw-r--r--tools/run_tests/post_test_node.bat30
-rw-r--r--tools/run_tests/pre_build_node.bat11
-rwxr-xr-xtools/run_tests/run_interop_tests.py6
-rw-r--r--tools/run_tests/run_node.bat1
-rwxr-xr-xtools/run_tests/run_python.sh7
-rwxr-xr-xtools/run_tests/run_tests.py31
52 files changed, 563 insertions, 438 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d549c5d208..3f7519a1d7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -13,7 +13,7 @@ In order to protect both you and ourselves, you will need to sign the
### Technical requirements
You will need several tools to work with this repository. In addition to all of
-the packages described in the [INSTALL](INSTALL) file, you will also need
+the packages described in the [INSTALL](INSTALL.md) file, you will also need
python, and the mako template renderer. To install the latter, using pip, one
should simply be able to do `pip install mako`.
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index e33f8970a9..0000000000
--- a/INSTALL
+++ /dev/null
@@ -1,217 +0,0 @@
-These instructions only cover building grpc C and C++ libraries under
-typical unix systems. If you need more information, please try grpc's
-wiki pages:
-
- https://github.com/google/grpc/wiki
-
-
-*************************
-* If you are in a hurry *
-*************************
-
-On Linux (Debian):
-
- Note: you will need to add the Debian 'jessie-backports' distribution to your sources
- file first.
-
- Add the following line to your `/etc/apt/sources.list` file:
-
- deb http://http.debian.net/debian jessie-backports main
-
- Install the gRPC library:
-
- $ [sudo] apt-get install libgrpc-dev
-
-OR
-
- $ git clone https://github.com/grpc/grpc.git
- $ cd grpc
- $ git submodule update --init
- $ make
- $ [sudo] make install
-
-You don't need anything else than GNU Make, gcc and autotools. Under a Debian
-or Ubuntu system, this should boil down to the following packages:
-
- $ [sudo] apt-get install build-essential autoconf libtool
-
-Building the python wrapper requires the following:
-
- $ [sudo] apt-get install python-all-dev python-virtualenv
-
-If you want to install in a different directory than the default /usr/lib, you can
-override it on the command line:
-
- $ [sudo] make install prefix=/opt
-
-
-*******************************
-* More detailled instructions *
-*******************************
-
-Setting up dependencies
-=======================
-
-Dependencies to compile the libraries
--------------------------------------
-
-grpc libraries have few external dependencies. If you need to compile and
-install them, they are present in the third_party directory if you have
-cloned the github repository recursively. If you didn't clone recursively,
-you can still get them later by running the following command:
-
- $ git submodule update --init
-
-Note that the Makefile makes it much easier for you to compile from sources
-if you were to clone recursively our git repository: it will automatically
-compile zlib and OpenSSL, which are core requirements for grpc. Note this
-creates grpc libraries that will have zlib and OpenSSL built-in inside of them,
-which significantly increases the libraries' size.
-
-In order to decrease that size, you can manually install zlib and OpenSSL on
-your system, so that the Makefile can use them instead.
-
-Under a Debian or Ubuntu system, one can acquire the development package
-for zlib this way:
-
- # apt-get install zlib1g-dev
-
-To the best of our knowledge, no distribution has an OpenSSL package that
-supports ALPN yet, so you would still have to depend on installing from source
-for that particular dependency if you want to reduce the libraries' size.
-
-The recommended version of OpenSSL that provides ALPN support is available
-at this URL:
-
- https://www.openssl.org/source/openssl-1.0.2.tar.gz
-
-
-Dependencies to compile and run the tests
------------------------------------------
-
-Compiling and running grpc plain-C tests dont't require any more dependency.
-
-
-Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and
-gflags. Although gflags is provided in third_party, you will need to manually
-install that dependency on your system to run these tests.
-
-Under a Debian or Ubuntu system, you can install the gtests and gflags packages
-using apt-get:
-
- # apt-get install libgflags-dev libgtest-dev
-
-However, protobuf 3.0.0 isn't in a debian package yet, but the Makefile will
-automatically try and compile the one present in third_party if you cloned the
-repository recursively, and that it detects your system is lacking it.
-
-Compiling and installing protobuf 3.0.0 requires a few more dependencies in
-itself, notably the autoconf suite. If you have apt-get, you can install
-these dependencies this way:
-
- # apt-get install autoconf libtool
-
-If you want to run the tests using one of the sanitized configurations, you
-will need clang and its instrumented libc++:
-
- # apt-get install clang libc++-dev
-
-Mac-specific notes:
--------------------
-
-For a Mac system, git is not available by default. You will first need to
-install Xcode from the Mac AppStore and then run the following command from a
-terminal:
-
- $ sudo xcode-select --install
-
-You should also install "port" following the instructions at
-https://www.macports.org . This will reside in /opt/local/bin/port for
-most Mac installations. Do the "git submodule" command listed above.
-
-Then execute the following for all the needed build dependencies
-
- $ sudo /opt/local/bin/port install autoconf automake libtool gflags cmake
- $ mkdir ~/gtest-svn
- $ svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
- $ mkdir mybuild
- $ cd mybuild
- $ cmake ../gtest-svn
- $ make
- $ make gtest.a gtest_main.a
- $ sudo cp libgtest.a libgtest_main.a /opt/local/lib
- $ sudo mkdir /opt/local/include/gtest
- $ sudo cp -pr ../gtest-svn/include/gtest /opt/local/include/gtest
-
-If you are going to make changes and need to regenerate the projects file,
-you will need to install certain modules for python.
-
- $ sudo easy_install simplejson mako
-
-Mingw-specific notes:
----------------------
-
-While gRPC compiles properly under mingw, some more preparation work is needed.
-The recommendation is to use msys2. The installation instructions are available
-at that address: http://msys2.github.io/
-
-Once this is installed, make sure you are using the following: MinGW-w64 Win64.
-You'll be required to install a few more packages:
-
- $ pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-zlib autoconf automake libtool
-
-Please also install OpenSSL from that website:
-
- http://slproweb.com/products/Win32OpenSSL.html
-
-The package Win64 OpenSSL v1.0.2a should do. At that point you should be able
-to compile gRPC with the following:
-
- $ export LDFLAGS="-L/mingw64/lib -L/c/OpenSSL-Win64"
- $ export CPPFLAGS="-I/mingw64/include -I/c/OpenSSL-Win64/include"
- $ make
-
-A word on OpenSSL
------------------
-
-Secure HTTP2 requires the TLS extension ALPN (see rfc 7301 and
-http://http2.github.io/http2-spec/ section 3.3). Our HTTP2 implementation
-relies on OpenSSL's implementation. OpenSSL 1.0.2 is the first released version
-of OpenSSL that has ALPN support, and this explains our dependency on it.
-
-Note that the Makefile supports compiling only the unsecure elements of grpc,
-and if you do not have OpenSSL and do not want it, you can still proceed
-with installing only the elements you require. However, we strongly recommend
-the use of encryption for all network traffic, and discourage the use of grpc
-without TLS.
-
-
-Compiling
-=========
-
-If you have all the dependencies mentioned above, you should simply be able
-to go ahead and run "make" to compile grpc's C and C++ libraries:
-
- $ make
-
-
-Testing
-=======
-
-To build and run the tests, you can run the command:
-
- $ make test
-
-If you want to be able to run them in parallel, and get better output, you can
-also use the python tool we have written:
-
- $ ./tools/run_tests/run_tests.py
-
-
-Installing
-==========
-
-Once everything is compiled, you should be able to install grpc C and C++
-libraries and headers:
-
- # make install
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000000..d9411db021
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,46 @@
+#If you are in a hurry
+
+For language-specific installation instructions for gRPC runtime, please
+refer to these documents
+
+ * [C++](examples/cpp)
+ * [C#](src/csharp): NuGet package `Grpc`
+ * [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc`
+ * [Java](https://github.com/grpc/grpc-java)
+ * [Node](src/node): `npm install grpc`
+ * [Objective-C](src/objective-c)
+ * [PHP](src/php): `pecl install grpc-beta`
+ * [Python](src/python/grpcio): `pip install grpcio`
+ * [Ruby](src/ruby): `gem install grpc`
+
+
+#Pre-requisites
+
+##Linux
+
+```sh
+ $ [sudo] apt-get install build-essential autoconf libtool
+```
+
+##Mac OSX
+
+For a Mac system, git is not available by default. You will first need to
+install Xcode from the Mac AppStore and then run the following command from a
+terminal:
+
+```sh
+ $ [sudo] xcode-select --install
+```
+
+#Build from Source
+
+For developers who are interested to contribute, here is how to compile the
+gRPC C Core library.
+
+```sh
+ $ git clone https://github.com/grpc/grpc.git
+ $ cd grpc
+ $ git submodule update --init
+ $ make
+ $ [sudo] make install
+```
diff --git a/README.md b/README.md
index 033e09b91b..abb4905392 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ You can find more detailed documentation and examples in the [doc](doc) and [exa
#Installation
-See [grpc/INSTALL](INSTALL) for installation instructions for various platforms.
+See [INSTALL](INSTALL.md) for installation instructions for various platforms.
#Repository Structure & Status
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index e618e967ee..3beb1d11f4 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -2,9 +2,8 @@ Interoperability Test Case Descriptions
=======================================
Client and server use
-[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto)
-and the [gRPC over HTTP/2 v2
-protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md).
+[test.proto](../src/proto/grpc/testing/test.proto)
+and the [gRPC over HTTP/2 v2 protocol](./PROTOCOL-HTTP2.md).
Client
------
diff --git a/examples/README.md b/examples/README.md
index 84ec80057e..cd85417ca2 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -447,4 +447,4 @@ $ greeter_client
## Read more!
- You can find links to language-specific tutorials, examples, and other docs in each language's [quick start](#quickstart).
-- [gRPC Authentication Support](doc/grpc-auth-support.md) introduces authentication support in gRPC with supported mechanisms and examples.
+- [gRPC Authentication Support](http://www.grpc.io/docs/guides/auth.html) introduces authentication support in gRPC with supported mechanisms and examples.
diff --git a/examples/cpp/README.md b/examples/cpp/README.md
index 85c495099b..e4b0eb698b 100644
--- a/examples/cpp/README.md
+++ b/examples/cpp/README.md
@@ -2,7 +2,7 @@
## Installation
-To install gRPC on your system, follow the instructions [here](../../INSTALL).
+To install gRPC on your system, follow the instructions [here](../../INSTALL.md).
## Hello C++ gRPC!
@@ -23,21 +23,6 @@ Change your current directory to examples/cpp/helloworld
$ cd examples/cpp/helloworld/
```
-
-### Generating gRPC code
-
-To generate the client and server side interfaces:
-
-```sh
-$ make helloworld.grpc.pb.cc helloworld.pb.cc
-```
-Which internally invokes the proto-compiler as:
-
-```sh
-$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
-$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
-```
-
### Client and server implementations
The client implementation is at [greeter_client.cc](helloworld/greeter_client.cc).
diff --git a/examples/cpp/cpptutorial.md b/examples/cpp/cpptutorial.md
index cd1cddb111..ef9ca99c0f 100644
--- a/examples/cpp/cpptutorial.md
+++ b/examples/cpp/cpptutorial.md
@@ -91,7 +91,7 @@ message Point {
Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C++ plugin.
-For simplicity, we've provided a [makefile](route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](../../INSTALL) first):
+For simplicity, we've provided a [makefile](route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](../../INSTALL.md) first):
```shell
$ make route_guide.grpc.pb.cc route_guide.pb.cc
diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md
index 90f3d6b147..8e11f7cdf3 100644
--- a/examples/cpp/helloworld/README.md
+++ b/examples/cpp/helloworld/README.md
@@ -2,7 +2,7 @@
### Install gRPC
Make sure you have installed gRPC on your system. Follow the instructions here:
-[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL).
+[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL.md).
### Get the tutorial source code
diff --git a/examples/node/README.md b/examples/node/README.md
index 7a2bc9794f..c1ef6b05ab 100644
--- a/examples/node/README.md
+++ b/examples/node/README.md
@@ -20,7 +20,7 @@ TRY IT!
- Run the server
```sh
- $ # from this directory (grpc_common/node).
+ $ # from this directory
$ node ./greeter_server.js &
```
diff --git a/grpc.def b/grpc.def
index bd0bc85a7c..f81aa1b05a 100644
--- a/grpc.def
+++ b/grpc.def
@@ -182,6 +182,7 @@ EXPORTS
gpr_event_wait
gpr_ref_init
gpr_ref
+ gpr_ref_non_zero
gpr_refn
gpr_unref
gpr_stats_init
diff --git a/include/grpc/impl/codegen/sync.h b/include/grpc/impl/codegen/sync.h
index d2f19d37d6..6fd7d64b29 100644
--- a/include/grpc/impl/codegen/sync.h
+++ b/include/grpc/impl/codegen/sync.h
@@ -182,6 +182,10 @@ GPRAPI void gpr_ref_init(gpr_refcount *r, int n);
/* Increment the reference count *r. Requires *r initialized. */
GPRAPI void gpr_ref(gpr_refcount *r);
+/* Increment the reference count *r. Requires *r initialized.
+ Crashes if refcount is zero */
+GPRAPI void gpr_ref_non_zero(gpr_refcount *r);
+
/* Increment the reference count *r by n. Requires *r initialized, n > 0. */
GPRAPI void gpr_refn(gpr_refcount *r, int n);
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index eeac3c146c..d4ba950818 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -251,7 +251,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
- GPR_ASSERT(op->set_accept_stream == NULL);
+ GPR_ASSERT(op->set_accept_stream == false);
if (op->bind_pollset != NULL) {
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
op->bind_pollset);
diff --git a/src/core/channel/client_uchannel.c b/src/core/channel/client_uchannel.c
index b1e7155773..83fcc3a87f 100644
--- a/src/core/channel/client_uchannel.c
+++ b/src/core/channel/client_uchannel.c
@@ -107,7 +107,7 @@ static void cuc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
- GPR_ASSERT(op->set_accept_stream == NULL);
+ GPR_ASSERT(op->set_accept_stream == false);
GPR_ASSERT(op->bind_pollset == NULL);
if (op->on_connectivity_state_change != NULL) {
diff --git a/src/core/channel/subchannel_call_holder.c b/src/core/channel/subchannel_call_holder.c
index 81297c8d44..8f46885a04 100644
--- a/src/core/channel/subchannel_call_holder.c
+++ b/src/core/channel/subchannel_call_holder.c
@@ -168,21 +168,23 @@ retry:
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
grpc_subchannel_call_holder *holder = arg;
- grpc_subchannel_call *call;
gpr_mu_lock(&holder->mu);
GPR_ASSERT(holder->creation_phase ==
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
- call = GET_CALL(holder);
- GPR_ASSERT(call == NULL || call == CANCELLED_CALL);
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
if (holder->connected_subchannel == NULL) {
fail_locked(exec_ctx, holder);
} else {
- gpr_atm_rel_store(
- &holder->subchannel_call,
- (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
- exec_ctx, holder->connected_subchannel, holder->pollset));
- retry_waiting_locked(exec_ctx, holder);
+ if (!gpr_atm_rel_cas(
+ &holder->subchannel_call, 0,
+ (gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
+ exec_ctx, holder->connected_subchannel, holder->pollset))) {
+ GPR_ASSERT(gpr_atm_acq_load(&holder->subchannel_call) == 1);
+ /* if this cas fails, the call was cancelled before the pick completed */
+ fail_locked(exec_ctx, holder);
+ } else {
+ retry_waiting_locked(exec_ctx, holder);
+ }
}
gpr_mu_unlock(&holder->mu);
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c
index 04580150f3..9c89c2c08a 100644
--- a/src/core/iomgr/iomgr.c
+++ b/src/core/iomgr/iomgr.c
@@ -41,9 +41,11 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/timer.h"
+#include "src/core/support/env.h"
#include "src/core/support/string.h"
static gpr_mu g_mu;
@@ -116,6 +118,9 @@ void grpc_iomgr_shutdown(void) {
"memory leaks are likely",
count_objects());
dump_objects("LEAKED");
+ if (grpc_iomgr_abort_on_leaks()) {
+ abort();
+ }
}
break;
}
@@ -154,3 +159,14 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
gpr_mu_unlock(&g_mu);
gpr_free(obj->name);
}
+
+bool grpc_iomgr_abort_on_leaks(void) {
+ char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
+ if (env == NULL) return false;
+ static const char *truthy[] = {"yes", "Yes", "YES", "true",
+ "True", "TRUE", "1"};
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
+ if (0 == strcmp(env, truthy[i])) return true;
+ }
+ return false;
+}
diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_internal.h
index e372c18e8a..ac2c46ebe6 100644
--- a/src/core/iomgr/iomgr_internal.h
+++ b/src/core/iomgr/iomgr_internal.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
@@ -34,6 +34,8 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
+#include <stdbool.h>
+
#include "src/core/iomgr/iomgr.h"
#include <grpc/support/sync.h>
@@ -55,4 +57,6 @@ void grpc_iomgr_platform_flush(void);
/** tear down all platform specific global iomgr structures */
void grpc_iomgr_platform_shutdown(void);
+bool grpc_iomgr_abort_on_leaks(void);
+
#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H */
diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
index 4dddfff230..92d6fb7241 100644
--- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c
+++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
@@ -122,6 +122,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
} else {
h->fds[fd_count++] = h->fds[i];
watchers[pfd_count].fd = h->fds[i];
+ GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start");
pfds[pfd_count].fd = h->fds[i]->fd;
pfds[pfd_count].revents = 0;
pfd_count++;
@@ -135,8 +136,10 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
gpr_mu_unlock(&pollset->mu);
for (i = 2; i < pfd_count; i++) {
- pfds[i].events = (short)grpc_fd_begin_poll(watchers[i].fd, pollset, worker,
- POLLIN, POLLOUT, &watchers[i]);
+ grpc_fd *fd = watchers[i].fd;
+ pfds[i].events = (short)grpc_fd_begin_poll(fd, pollset, worker, POLLIN,
+ POLLOUT, &watchers[i]);
+ GRPC_FD_UNREF(fd, "multipoller_start");
}
/* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
diff --git a/src/core/support/sync.c b/src/core/support/sync.c
index d368422d9e..69e3e39c5c 100644
--- a/src/core/support/sync.c
+++ b/src/core/support/sync.c
@@ -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
@@ -98,6 +98,11 @@ void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
+void gpr_ref_non_zero(gpr_refcount *r) {
+ gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
+ GPR_ASSERT(prior > 0);
+}
+
void gpr_refn(gpr_refcount *r, int n) {
gpr_atm_no_barrier_fetch_add(&r->count, n);
}
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index fb5e0d4b9e..5b13d4ba52 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -407,8 +407,15 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
maybe_finish_shutdown(exec_ctx, chand->server);
chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
chand->finish_destroy_channel_closure.cb_arg = chand;
- grpc_exec_ctx_enqueue(exec_ctx, &chand->finish_destroy_channel_closure, true,
- NULL);
+
+ grpc_transport_op op;
+ memset(&op, 0, sizeof(op));
+ op.set_accept_stream = true;
+ op.on_consumed = &chand->finish_destroy_channel_closure;
+ grpc_channel_next_op(exec_ctx,
+ grpc_channel_stack_element(
+ grpc_channel_get_channel_stack(chand->channel), 0),
+ &op);
}
static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
@@ -971,7 +978,8 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
memset(&op, 0, sizeof(op));
- op.set_accept_stream = accept_stream;
+ op.set_accept_stream = true;
+ op.set_accept_stream_fn = accept_stream;
op.set_accept_stream_user_data = chand;
op.on_connectivity_state_change = &chand->channel_connectivity_changed;
op.connectivity_state = &chand->connectivity_state;
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
index d76d31be23..b720d1ab3e 100644
--- a/src/core/transport/chttp2/internal.h
+++ b/src/core/transport/chttp2/internal.h
@@ -358,6 +358,9 @@ struct grpc_chttp2_transport {
/** connectivity tracking */
grpc_connectivity_state_tracker state_tracker;
} channel_callback;
+
+ /** Transport op to be applied post-parsing */
+ grpc_transport_op *post_parsing_op;
};
typedef struct {
@@ -417,7 +420,7 @@ typedef struct {
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
uint32_t id;
uint8_t fetching;
- uint8_t sent_initial_metadata;
+ bool sent_initial_metadata;
uint8_t sent_message;
uint8_t sent_trailing_metadata;
uint8_t read_closed;
@@ -509,7 +512,7 @@ void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
-void grpc_chttp2_list_add_writable_stream(
+bool grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
/** Get a writable stream
@@ -519,14 +522,13 @@ int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
-void grpc_chttp2_list_remove_writable_stream(
+bool grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
- grpc_chttp2_stream_global *stream_global);
+ grpc_chttp2_stream_global *stream_global) GRPC_MUST_USE_RESULT;
-/* returns 1 if stream added, 0 if it was already present */
-int grpc_chttp2_list_add_writing_stream(
+void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
- grpc_chttp2_stream_writing *stream_writing) GRPC_MUST_USE_RESULT;
+ grpc_chttp2_stream_writing *stream_writing);
int grpc_chttp2_list_have_writing_streams(
grpc_chttp2_transport_writing *transport_writing);
int grpc_chttp2_list_pop_writing_stream(
@@ -770,4 +772,9 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *parsing,
const uint8_t *opaque_8bytes);
+/** add a ref to the stream and add it to the writable list;
+ ref will be dropped in writing.c */
+void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
+ grpc_chttp2_stream_global *stream_global);
+
#endif
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
index 8fdebd7f13..0516f39fa9 100644
--- a/src/core/transport/chttp2/parsing.c
+++ b/src/core/transport/chttp2/parsing.c
@@ -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
@@ -149,7 +149,7 @@ void grpc_chttp2_publish_reads(
if (was_zero && !is_zero) {
while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
&stream_global)) {
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@@ -178,7 +178,7 @@ void grpc_chttp2_publish_reads(
outgoing_window);
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c
index b284c78818..60fe735cfc 100644
--- a/src/core/transport/chttp2/stream_lists.c
+++ b/src/core/transport/chttp2/stream_lists.c
@@ -100,11 +100,14 @@ static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
}
}
-static void stream_list_maybe_remove(grpc_chttp2_transport *t,
+static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
if (s->included[id]) {
stream_list_remove(t, s, id);
+ return true;
+ } else {
+ return false;
}
}
@@ -125,23 +128,24 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
s->included[id] = 1;
}
-static int stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
- grpc_chttp2_stream_list_id id) {
+static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
+ grpc_chttp2_stream_list_id id) {
if (s->included[id]) {
- return 0;
+ return false;
}
stream_list_add_tail(t, s, id);
- return 1;
+ return true;
}
/* wrappers for specializations */
-void grpc_chttp2_list_add_writable_stream(
+bool grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
GPR_ASSERT(stream_global->id != 0);
- stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
- STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
+ return stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+ STREAM_FROM_GLOBAL(stream_global),
+ GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_pop_writable_stream(
@@ -159,20 +163,20 @@ int grpc_chttp2_list_pop_writable_stream(
return r;
}
-void grpc_chttp2_list_remove_writable_stream(
+bool grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
- stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
- STREAM_FROM_GLOBAL(stream_global),
- GRPC_CHTTP2_LIST_WRITABLE);
+ return stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
+ STREAM_FROM_GLOBAL(stream_global),
+ GRPC_CHTTP2_LIST_WRITABLE);
}
-int grpc_chttp2_list_add_writing_stream(
+void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) {
- return stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
- STREAM_FROM_WRITING(stream_writing),
- GRPC_CHTTP2_LIST_WRITING);
+ GPR_ASSERT(stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
+ STREAM_FROM_WRITING(stream_writing),
+ GRPC_CHTTP2_LIST_WRITING));
}
int grpc_chttp2_list_have_writing_streams(
@@ -332,7 +336,7 @@ void grpc_chttp2_list_flush_writing_stalled_by_transport(
while (stream_list_pop(transport, &stream,
GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) {
if (is_window_available) {
- grpc_chttp2_list_add_writable_stream(&transport->global, &stream->global);
+ grpc_chttp2_become_writable(&transport->global, &stream->global);
} else {
grpc_chttp2_list_add_stalled_by_transport(transport_writing,
&stream->writing);
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
index 356fd8174a..107725cbc7 100644
--- a/src/core/transport/chttp2/writing.c
+++ b/src/core/transport/chttp2/writing.c
@@ -83,7 +83,8 @@ int grpc_chttp2_unlocking_check_writes(
(according to available window sizes) and add to the output buffer */
while (grpc_chttp2_list_pop_writable_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
- uint8_t sent_initial_metadata;
+ bool sent_initial_metadata = stream_writing->sent_initial_metadata;
+ bool become_writable = false;
stream_writing->id = stream_global->id;
stream_writing->read_closed = stream_global->read_closed;
@@ -92,16 +93,12 @@ int grpc_chttp2_unlocking_check_writes(
outgoing_window, stream_global,
outgoing_window);
- sent_initial_metadata = stream_writing->sent_initial_metadata;
if (!sent_initial_metadata && stream_global->send_initial_metadata) {
stream_writing->send_initial_metadata =
stream_global->send_initial_metadata;
stream_global->send_initial_metadata = NULL;
- if (grpc_chttp2_list_add_writing_stream(transport_writing,
- stream_writing)) {
- GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
- }
- sent_initial_metadata = 1;
+ become_writable = true;
+ sent_initial_metadata = true;
}
if (sent_initial_metadata) {
if (stream_global->send_message != NULL) {
@@ -128,10 +125,7 @@ int grpc_chttp2_unlocking_check_writes(
stream_writing->flow_controlled_buffer.length > 0) &&
stream_writing->outgoing_window > 0) {
if (transport_writing->outgoing_window > 0) {
- if (grpc_chttp2_list_add_writing_stream(transport_writing,
- stream_writing)) {
- GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
- }
+ become_writable = true;
} else {
grpc_chttp2_list_add_stalled_by_transport(transport_writing,
stream_writing);
@@ -141,10 +135,7 @@ int grpc_chttp2_unlocking_check_writes(
stream_writing->send_trailing_metadata =
stream_global->send_trailing_metadata;
stream_global->send_trailing_metadata = NULL;
- if (grpc_chttp2_list_add_writing_stream(transport_writing,
- stream_writing)) {
- GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
- }
+ become_writable = true;
}
}
@@ -153,10 +144,13 @@ int grpc_chttp2_unlocking_check_writes(
GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing,
announce_window, stream_global,
unannounced_incoming_window_for_writing);
- if (grpc_chttp2_list_add_writing_stream(transport_writing,
- stream_writing)) {
- GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
- }
+ become_writable = true;
+ }
+
+ if (become_writable) {
+ grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
+ } else {
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
}
}
@@ -310,10 +304,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
(stream_writing->send_message && !stream_writing->fetching)) &&
stream_writing->outgoing_window > 0) {
if (transport_writing->outgoing_window > 0) {
- if (grpc_chttp2_list_add_writing_stream(transport_writing,
- stream_writing)) {
- /* do nothing - already reffed */
- }
+ grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
} else {
grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
stream_writing);
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index b9f511e946..19265252ca 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -142,7 +142,7 @@ static void incoming_byte_stream_update_flow_control(
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global);
-/*
+/*******************************************************************************
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
*/
@@ -432,6 +432,14 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
if (t->ep) {
allow_endpoint_shutdown_locked(exec_ctx, t);
}
+
+ /* flush writable stream list to avoid dangling references */
+ grpc_chttp2_stream_global *stream_global;
+ grpc_chttp2_stream_writing *stream_writing;
+ while (grpc_chttp2_list_pop_writable_stream(
+ &t->global, &t->writing, &stream_global, &stream_writing)) {
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
+ }
}
}
@@ -521,7 +529,6 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
s->global.id) == NULL);
}
- grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
&s->global);
grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global);
@@ -583,7 +590,7 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
return &accepting->parsing;
}
-/*
+/*******************************************************************************
* LOCK MANAGEMENT
*/
@@ -611,10 +618,18 @@ static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
GPR_TIMER_END("unlock", 0);
}
-/*
+/*******************************************************************************
* OUTPUT PROCESSING
*/
+void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
+ grpc_chttp2_stream_global *stream_global) {
+ if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
+ grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
+ GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
+ }
+}
+
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
uint32_t value) {
const grpc_chttp2_setting_parameters *sp =
@@ -732,7 +747,7 @@ static void maybe_start_some_streams(
stream_global->id, STREAM_FROM_GLOBAL(stream_global));
stream_global->in_stream_map = 1;
transport_global->concurrent_stream_count++;
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
/* cancel out streams that will never be started */
while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@@ -821,7 +836,7 @@ static void perform_stream_op_locked(
maybe_start_some_streams(exec_ctx, transport_global);
} else {
GPR_ASSERT(stream_global->id != 0);
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
} else {
grpc_chttp2_complete_closure_step(
@@ -838,7 +853,7 @@ static void perform_stream_op_locked(
exec_ctx, &stream_global->send_message_finished, 0);
} else if (stream_global->id != 0) {
stream_global->send_message = op->send_message;
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@@ -858,7 +873,7 @@ static void perform_stream_op_locked(
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@@ -944,12 +959,10 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
unlock(exec_ctx, t);
}
-static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_transport_op *op) {
- grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
- int close_transport = 0;
-
- lock(t);
+static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
+ grpc_chttp2_transport *t,
+ grpc_transport_op *op) {
+ bool close_transport = false;
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
@@ -968,8 +981,8 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
close_transport = !grpc_chttp2_has_streams(t);
}
- if (op->set_accept_stream != NULL) {
- t->channel_callback.accept_stream = op->set_accept_stream;
+ if (op->set_accept_stream) {
+ t->channel_callback.accept_stream = op->set_accept_stream_fn;
t->channel_callback.accept_stream_user_data =
op->set_accept_stream_user_data;
}
@@ -990,16 +1003,31 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
close_transport_locked(exec_ctx, t);
}
- unlock(exec_ctx, t);
-
if (close_transport) {
- lock(t);
close_transport_locked(exec_ctx, t);
- unlock(exec_ctx, t);
}
}
-/*
+static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_transport_op *op) {
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+
+ lock(t);
+
+ /* If there's a set_accept_stream ensure that we're not parsing
+ to avoid changing things out from underneath */
+ if (t->parsing_active && op->set_accept_stream) {
+ GPR_ASSERT(t->post_parsing_op == NULL);
+ t->post_parsing_op = gpr_malloc(sizeof(*op));
+ memcpy(t->post_parsing_op, op, sizeof(*op));
+ } else {
+ perform_transport_op_locked(exec_ctx, t, op);
+ }
+
+ unlock(exec_ctx, t);
+}
+
+/*******************************************************************************
* INPUT PROCESSING
*/
@@ -1064,7 +1092,6 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (!s) {
s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
}
- grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
GPR_ASSERT(s);
s->global.in_stream_map = 0;
if (t->parsing.incoming_stream == &s->parsing) {
@@ -1080,6 +1107,9 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(exec_ctx, t);
}
+ if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
+ GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
+ }
new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
grpc_chttp2_stream_map_size(&t->new_stream_map);
@@ -1331,7 +1361,7 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@@ -1392,6 +1422,13 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
/* handle higher level things */
grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
t->parsing_active = 0;
+ /* handle delayed transport ops (if there is one) */
+ if (t->post_parsing_op) {
+ grpc_transport_op *op = t->post_parsing_op;
+ t->post_parsing_op = NULL;
+ perform_transport_op_locked(exec_ctx, t, op);
+ gpr_free(op);
+ }
/* if a stream is in the stream map, and gets cancelled, we need to ensure
* we are not parsing before continuing the cancellation to keep things in
* a sane state */
@@ -1426,7 +1463,7 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
GPR_TIMER_END("recv_data", 0);
}
-/*
+/*******************************************************************************
* CALLBACK LOOP
*/
@@ -1440,7 +1477,7 @@ static void connectivity_state_set(
state, reason);
}
-/*
+/*******************************************************************************
* POLLSET STUFF
*/
@@ -1468,7 +1505,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
unlock(exec_ctx, t);
}
-/*
+/*******************************************************************************
* BYTE STREAM
*/
@@ -1508,7 +1545,7 @@ static void incoming_byte_stream_update_flow_control(
add_max_recv_bytes);
grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
stream_global);
- grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+ grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@@ -1623,7 +1660,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
return incoming_byte_stream;
}
-/*
+/*******************************************************************************
* TRACING
*/
@@ -1709,7 +1746,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
gpr_free(prefix);
}
-/*
+/*******************************************************************************
* INTEGRATION GLUE
*/
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index 14912af7df..807ae071a3 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -43,11 +43,13 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
+
#include "src/core/profiling/timers.h"
#include "src/core/support/murmur_hash.h"
#include "src/core/support/string.h"
#include "src/core/transport/chttp2/bin_encoder.h"
#include "src/core/transport/static_metadata.h"
+#include "src/core/iomgr/iomgr_internal.h"
/* There are two kinds of mdelem and mdstr instances.
* Static instances are declared in static_metadata.{h,c} and
@@ -227,6 +229,9 @@ void grpc_mdctx_global_shutdown(void) {
if (shard->count != 0) {
gpr_log(GPR_DEBUG, "WARNING: %d metadata elements were leaked",
shard->count);
+ if (grpc_iomgr_abort_on_leaks()) {
+ abort();
+ }
}
gpr_free(shard->elems);
}
@@ -237,6 +242,9 @@ void grpc_mdctx_global_shutdown(void) {
if (shard->count != 0) {
gpr_log(GPR_DEBUG, "WARNING: %d metadata strings were leaked",
shard->count);
+ if (grpc_iomgr_abort_on_leaks()) {
+ abort();
+ }
}
gpr_free(shard->strs);
}
diff --git a/src/core/transport/transport.c b/src/core/transport/transport.c
index 6e154b629a..3b555fa933 100644
--- a/src/core/transport/transport.c
+++ b/src/core/transport/transport.c
@@ -45,7 +45,7 @@ void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
#else
void grpc_stream_ref(grpc_stream_refcount *refcount) {
#endif
- gpr_ref(&refcount->refs);
+ gpr_ref_non_zero(&refcount->refs);
}
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
diff --git a/src/core/transport/transport.h b/src/core/transport/transport.h
index 8902c5d2f6..ed6e121c9c 100644
--- a/src/core/transport/transport.h
+++ b/src/core/transport/transport.h
@@ -123,7 +123,7 @@ typedef struct grpc_transport_stream_op {
/** Transport op: a set of operations to perform on a transport as a whole */
typedef struct grpc_transport_op {
- /** called when processing of this op is done */
+ /** Called when processing of this op is done. */
grpc_closure *on_consumed;
/** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
grpc_closure *on_connectivity_state_change;
@@ -138,9 +138,13 @@ typedef struct grpc_transport_op {
grpc_status_code goaway_status;
gpr_slice *goaway_message;
/** set the callback for accepting new streams;
- this is a permanent callback, unlike the other one-shot closures */
- void (*set_accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data,
- grpc_transport *transport, const void *server_data);
+ this is a permanent callback, unlike the other one-shot closures.
+ If true, the callback is set to set_accept_stream_fn, with its
+ user_data argument set to set_accept_stream_user_data */
+ bool set_accept_stream;
+ void (*set_accept_stream_fn)(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_transport *transport,
+ const void *server_data);
void *set_accept_stream_user_data;
/** add this transport to a pollset */
grpc_pollset *bind_pollset;
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index db383e4d00..5602011a8e 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -290,6 +290,7 @@ function timeoutOnSleepingServer(client, done) {
call.write({
payload: {body: zeroBuffer(27182)}
});
+ call.on('data', function() {});
call.on('error', function(error) {
assert(error.code === grpc.status.DEADLINE_EXCEEDED ||
@@ -336,6 +337,7 @@ function customMetadata(client, done) {
['test_initial_metadata_value']);
done();
});
+ stream.on('data', function() {});
stream.on('status', function(status) {
var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY);
assert(echo_trailer.length > 0);
@@ -361,6 +363,7 @@ function statusCodeAndMessage(client, done) {
done();
});
var duplex = client.fullDuplexCall();
+ duplex.on('data', function() {});
duplex.on('status', function(status) {
assert(status);
assert.strictEqual(status.code, 2);
diff --git a/src/node/src/client.js b/src/node/src/client.js
index c65dd73650..9acf51bd98 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -131,9 +131,69 @@ function ClientReadableStream(call, deserialize) {
this.finished = false;
this.reading = false;
this.deserialize = common.wrapIgnoreNull(deserialize);
+ /* Status generated from reading messages from the server. Overrides the
+ * status from the server if not OK */
+ this.read_status = null;
+ /* Status received from the server. */
+ this.received_status = null;
}
/**
+ * Called when all messages from the server have been processed. The status
+ * parameter indicates that the call should end with that status. status
+ * defaults to OK if not provided.
+ * @param {Object!} status The status that the call should end with
+ */
+function _readsDone(status) {
+ /* jshint validthis: true */
+ if (!status) {
+ status = {code: grpc.status.OK, details: 'OK'};
+ }
+ this.finished = true;
+ this.read_status = status;
+ this._emitStatusIfDone();
+}
+
+ClientReadableStream.prototype._readsDone = _readsDone;
+
+/**
+ * Called to indicate that we have received a status from the server.
+ */
+function _receiveStatus(status) {
+ /* jshint validthis: true */
+ this.received_status = status;
+ this._emitStatusIfDone();
+}
+
+ClientReadableStream.prototype._receiveStatus = _receiveStatus;
+
+/**
+ * If we have both processed all incoming messages and received the status from
+ * the server, emit the status. Otherwise, do nothing.
+ */
+function _emitStatusIfDone() {
+ /* jshint validthis: true */
+ var status;
+ if (this.read_status && this.received_status) {
+ if (this.read_status.code !== grpc.status.OK) {
+ status = this.read_status;
+ } else {
+ status = this.received_status;
+ }
+ this.emit('status', status);
+ if (status.code !== grpc.status.OK) {
+ var error = new Error(status.details);
+ error.code = status.code;
+ error.metadata = status.metadata;
+ this.emit('error', error);
+ return;
+ }
+ }
+}
+
+ClientReadableStream.prototype._emitStatusIfDone = _emitStatusIfDone;
+
+/**
* Read the next object from the stream.
* @access private
* @param {*} size Ignored because we use objectMode=true
@@ -150,6 +210,7 @@ function _read(size) {
if (err) {
// Something has gone wrong. Stop reading and wait for status
self.finished = true;
+ self._readsDone();
return;
}
var data = event.read;
@@ -157,8 +218,11 @@ function _read(size) {
try {
deserialized = self.deserialize(data);
} catch (e) {
- self.call.cancelWithStatus(grpc.status.INTERNAL,
- 'Failed to parse server response');
+ self._readsDone({code: grpc.status.INTERNAL,
+ details: 'Failed to parse server response'});
+ }
+ if (data === null) {
+ self._readsDone();
}
if (self.push(deserialized) && data !== null) {
var read_batch = {};
@@ -198,6 +262,11 @@ function ClientDuplexStream(call, serialize, deserialize) {
this.serialize = common.wrapIgnoreNull(serialize);
this.deserialize = common.wrapIgnoreNull(deserialize);
this.call = call;
+ /* Status generated from reading messages from the server. Overrides the
+ * status from the server if not OK */
+ this.read_status = null;
+ /* Status received from the server. */
+ this.received_status = null;
this.on('finish', function() {
var batch = {};
batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
@@ -205,6 +274,9 @@ function ClientDuplexStream(call, serialize, deserialize) {
});
}
+ClientDuplexStream.prototype._readsDone = _readsDone;
+ClientDuplexStream.prototype._receiveStatus = _receiveStatus;
+ClientDuplexStream.prototype._emitStatusIfDone = _emitStatusIfDone;
ClientDuplexStream.prototype._read = _read;
ClientDuplexStream.prototype._write = _write;
@@ -487,22 +559,13 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
var status_batch = {};
status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(status_batch, function(err, response) {
- response.status.metadata = Metadata._fromCoreRepresentation(
- response.status.metadata);
- stream.emit('status', response.status);
- if (response.status.code !== grpc.status.OK) {
- var error = new Error(response.status.details);
- error.code = response.status.code;
- error.metadata = response.status.metadata;
- stream.emit('error', error);
+ if (err) {
+ stream.emit('error', err);
return;
- } else {
- if (err) {
- // Got a batch error, but OK status. Something went wrong
- stream.emit('error', err);
- return;
- }
}
+ response.status.metadata = Metadata._fromCoreRepresentation(
+ response.status.metadata);
+ stream._receiveStatus(response.status);
});
return stream;
}
@@ -552,22 +615,13 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
var status_batch = {};
status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(status_batch, function(err, response) {
- response.status.metadata = Metadata._fromCoreRepresentation(
- response.status.metadata);
- stream.emit('status', response.status);
- if (response.status.code !== grpc.status.OK) {
- var error = new Error(response.status.details);
- error.code = response.status.code;
- error.metadata = response.status.metadata;
- stream.emit('error', error);
+ if (err) {
+ stream.emit('error', err);
return;
- } else {
- if (err) {
- // Got a batch error, but OK status. Something went wrong
- stream.emit('error', err);
- return;
- }
}
+ response.status.metadata = Metadata._fromCoreRepresentation(
+ response.status.metadata);
+ stream._receiveStatus(response.status);
});
return stream;
}
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 530f1f7749..8a232d6fc4 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -1000,6 +1000,7 @@ describe('Call propagation', function() {
proxy_impl.serverStream = function(parent) {
var child = client.serverStream(parent.request, null,
{parent: parent});
+ child.on('data', function() {});
child.on('error', function(err) {
assert(err);
assert.strictEqual(err.code, grpc.status.CANCELLED);
@@ -1013,6 +1014,7 @@ describe('Call propagation', function() {
var proxy_client = new Client('localhost:' + proxy_port,
grpc.credentials.createInsecure());
call = proxy_client.serverStream({});
+ call.on('data', function() {});
call.on('error', function(err) {
done();
});
@@ -1022,6 +1024,7 @@ describe('Call propagation', function() {
var call;
proxy_impl.bidiStream = function(parent) {
var child = client.bidiStream(null, {parent: parent});
+ child.on('data', function() {});
child.on('error', function(err) {
assert(err);
assert.strictEqual(err.code, grpc.status.CANCELLED);
@@ -1035,6 +1038,7 @@ describe('Call propagation', function() {
var proxy_client = new Client('localhost:' + proxy_port,
grpc.credentials.createInsecure());
call = proxy_client.bidiStream();
+ call.on('data', function() {});
call.on('error', function(err) {
done();
});
@@ -1074,6 +1078,7 @@ describe('Call propagation', function() {
proxy_impl.bidiStream = function(parent) {
var child = client.bidiStream(
null, {parent: parent, propagate_flags: deadline_flags});
+ child.on('data', function() {});
child.on('error', function(err) {
assert(err);
assert(err.code === grpc.status.DEADLINE_EXCEEDED ||
@@ -1089,6 +1094,7 @@ describe('Call propagation', function() {
var deadline = new Date();
deadline.setSeconds(deadline.getSeconds() + 1);
var call = proxy_client.bidiStream(null, {deadline: deadline});
+ call.on('data', function() {});
call.on('error', function(err) {
done();
});
@@ -1130,6 +1136,7 @@ describe('Cancelling surface client', function() {
});
it('Should correctly cancel a server stream call', function(done) {
var call = client.fib({'limit': 5});
+ call.on('data', function() {});
call.on('error', function(error) {
assert.strictEqual(error.code, surface_client.status.CANCELLED);
done();
@@ -1138,6 +1145,7 @@ describe('Cancelling surface client', function() {
});
it('Should correctly cancel a bidi stream call', function(done) {
var call = client.divMany();
+ call.on('data', function() {});
call.on('error', function(error) {
assert.strictEqual(error.code, surface_client.status.CANCELLED);
done();
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
index fe3b8f39d1..7b66cd4c32 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.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
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
index ea2b01ee1d..ff3031678c 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
@@ -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
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index 4b1860ce8c..8bd6ae6372 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/imports.generated.c
@@ -220,6 +220,7 @@ gpr_event_get_type gpr_event_get_import;
gpr_event_wait_type gpr_event_wait_import;
gpr_ref_init_type gpr_ref_init_import;
gpr_ref_type gpr_ref_import;
+gpr_ref_non_zero_type gpr_ref_non_zero_import;
gpr_refn_type gpr_refn_import;
gpr_unref_type gpr_unref_import;
gpr_stats_init_type gpr_stats_init_import;
@@ -485,6 +486,7 @@ void pygrpc_load_imports(HMODULE library) {
gpr_event_wait_import = (gpr_event_wait_type) GetProcAddress(library, "gpr_event_wait");
gpr_ref_init_import = (gpr_ref_init_type) GetProcAddress(library, "gpr_ref_init");
gpr_ref_import = (gpr_ref_type) GetProcAddress(library, "gpr_ref");
+ gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero");
gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn");
gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref");
gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init");
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index a395dce7d6..b70dcccd17 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/imports.generated.h
@@ -610,6 +610,9 @@ extern gpr_ref_init_type gpr_ref_init_import;
typedef void(*gpr_ref_type)(gpr_refcount *r);
extern gpr_ref_type gpr_ref_import;
#define gpr_ref gpr_ref_import
+typedef void(*gpr_ref_non_zero_type)(gpr_refcount *r);
+extern gpr_ref_non_zero_type gpr_ref_non_zero_import;
+#define gpr_ref_non_zero gpr_ref_non_zero_import
typedef void(*gpr_refn_type)(gpr_refcount *r, int n);
extern gpr_refn_type gpr_refn_import;
#define gpr_refn gpr_refn_import
diff --git a/src/python/grpcio/tests/_runner.py b/src/python/grpcio/tests/_runner.py
index 4f1ddb57fc..38a5432e79 100644
--- a/src/python/grpcio/tests/_runner.py
+++ b/src/python/grpcio/tests/_runner.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -143,10 +143,17 @@ class Runner(object):
def run(self, suite):
"""See setuptools' test_runner setup argument for information."""
+ # only run test cases with id starting with given prefix
+ testcase_filter = os.getenv('GPRC_PYTHON_TESTRUNNER_FILTER')
+ filtered_cases = []
+ for case in _loader.iterate_suite_cases(suite):
+ if not testcase_filter or case.id().startswith(testcase_filter):
+ filtered_cases.append(case)
+
# Ensure that every test case has no collision with any other test case in
# the augmented results.
augmented_cases = [AugmentedCase(case, uuid.uuid4())
- for case in _loader.iterate_suite_cases(suite)]
+ for case in filtered_cases]
case_id_by_case = dict((augmented_case.case, augmented_case.id)
for augmented_case in augmented_cases)
result_out = StringIO.StringIO()
diff --git a/src/python/grpcio/tests/tests.json b/src/python/grpcio/tests/tests.json
new file mode 100644
index 0000000000..388d040d5c
--- /dev/null
+++ b/src/python/grpcio/tests/tests.json
@@ -0,0 +1,62 @@
+[
+ "_base_interface_test.AsyncEasyTest",
+ "_base_interface_test.AsyncPeasyTest",
+ "_base_interface_test.SyncEasyTest",
+ "_base_interface_test.SyncPeasyTest",
+ "_beta_features_test.BetaFeaturesTest",
+ "_beta_features_test.ContextManagementAndLifecycleTest",
+ "_channel_test.ChannelTest",
+ "_connectivity_channel_test.ChannelConnectivityTest",
+ "_core_over_links_base_interface_test.AsyncEasyTest",
+ "_core_over_links_base_interface_test.AsyncPeasyTest",
+ "_core_over_links_base_interface_test.SyncEasyTest",
+ "_core_over_links_base_interface_test.SyncPeasyTest",
+ "_crust_over_core_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
+ "_crust_over_core_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest",
+ "_crust_over_core_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_crust_over_core_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
+ "_crust_over_core_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest",
+ "_crust_over_core_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_crust_over_core_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
+ "_crust_over_core_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest",
+ "_crust_over_core_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_crust_over_core_over_links_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
+ "_crust_over_core_over_links_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest",
+ "_crust_over_core_over_links_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_crust_over_core_over_links_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
+ "_crust_over_core_over_links_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest",
+ "_crust_over_core_over_links_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_crust_over_core_over_links_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
+ "_crust_over_core_over_links_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest",
+ "_crust_over_core_over_links_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
+ "_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest",
+ "_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
+ "_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest",
+ "_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
+ "_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest",
+ "_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
+ "_implementations_test.ChannelCredentialsTest",
+ "_insecure_interop_test.InsecureInteropTest",
+ "_intermediary_low_test.CancellationTest",
+ "_intermediary_low_test.EchoTest",
+ "_intermediary_low_test.ExpirationTest",
+ "_intermediary_low_test.LonelyClientTest",
+ "_later_test.LaterTest",
+ "_logging_pool_test.LoggingPoolTest",
+ "_lonely_invocation_link_test.LonelyInvocationLinkTest",
+ "_low_test.HangingServerShutdown",
+ "_low_test.InsecureServerInsecureClient",
+ "_not_found_test.NotFoundTest",
+ "_sanity_test.Sanity",
+ "_secure_interop_test.SecureInteropTest",
+ "_transmission_test.RoundTripTest",
+ "_transmission_test.TransmissionTest",
+ "_utilities_test.ChannelConnectivityTest",
+ "beta_python_plugin_test.PythonPluginTest",
+ "cygrpc_test.InsecureServerInsecureClient",
+ "cygrpc_test.SecureServerSecureClient",
+ "cygrpc_test.TypeSmokeTest"
+] \ No newline at end of file
diff --git a/src/python/grpcio/tests/unit/_sanity/__init__.py b/src/python/grpcio/tests/unit/_sanity/__init__.py
new file mode 100644
index 0000000000..2f88fa0412
--- /dev/null
+++ b/src/python/grpcio/tests/unit/_sanity/__init__.py
@@ -0,0 +1,30 @@
+# Copyright 2016, 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.
+
+
diff --git a/src/python/grpcio/tests/unit/_sanity/_sanity_test.py b/src/python/grpcio/tests/unit/_sanity/_sanity_test.py
new file mode 100644
index 0000000000..0a5a715c0e
--- /dev/null
+++ b/src/python/grpcio/tests/unit/_sanity/_sanity_test.py
@@ -0,0 +1,53 @@
+# Copyright 2016, 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.
+
+import json
+import unittest
+
+import tests
+
+
+class Sanity(unittest.TestCase):
+
+ def testTestsJsonUpToDate(self):
+ """Autodiscovers all test suites and checks that tests.json is up to date"""
+ loader = tests.Loader()
+ loader.loadTestsFromNames(['tests'])
+ test_suite_names = [
+ test_case_class.id().rsplit('.', 1)[0]
+ for test_case_class in tests._loader.iterate_suite_cases(loader.suite)]
+ test_suite_names = sorted(set(test_suite_names))
+
+ with open('src/python/grpcio/tests/tests.json') as tests_json_file:
+ tests_json = json.load(tests_json_file)
+ self.assertListEqual(test_suite_names, tests_json)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 1af34d97fb..56db4ec686 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -220,6 +220,7 @@ gpr_event_get_type gpr_event_get_import;
gpr_event_wait_type gpr_event_wait_import;
gpr_ref_init_type gpr_ref_init_import;
gpr_ref_type gpr_ref_import;
+gpr_ref_non_zero_type gpr_ref_non_zero_import;
gpr_refn_type gpr_refn_import;
gpr_unref_type gpr_unref_import;
gpr_stats_init_type gpr_stats_init_import;
@@ -481,6 +482,7 @@ void grpc_rb_load_imports(HMODULE library) {
gpr_event_wait_import = (gpr_event_wait_type) GetProcAddress(library, "gpr_event_wait");
gpr_ref_init_import = (gpr_ref_init_type) GetProcAddress(library, "gpr_ref_init");
gpr_ref_import = (gpr_ref_type) GetProcAddress(library, "gpr_ref");
+ gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero");
gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn");
gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref");
gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 38aabfaca8..b972f60fc3 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -610,6 +610,9 @@ extern gpr_ref_init_type gpr_ref_init_import;
typedef void(*gpr_ref_type)(gpr_refcount *r);
extern gpr_ref_type gpr_ref_import;
#define gpr_ref gpr_ref_import
+typedef void(*gpr_ref_non_zero_type)(gpr_refcount *r);
+extern gpr_ref_non_zero_type gpr_ref_non_zero_import;
+#define gpr_ref_non_zero gpr_ref_non_zero_import
typedef void(*gpr_refn_type)(gpr_refcount *r, int n);
extern gpr_refn_type gpr_refn_import;
#define gpr_refn gpr_refn_import
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 3ad733e111..79a60cc860 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -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
@@ -30,7 +30,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
-// Test description at doc/connection-backoff-interop-test-description.md
+
#include <memory>
#include <sstream>
diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc
index 785f9c7ad5..3602b8c2b0 100644
--- a/test/cpp/interop/reconnect_interop_server.cc
+++ b/test/cpp/interop/reconnect_interop_server.cc
@@ -30,8 +30,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
-
-// Test description at doc/connection-backoff-interop-test-description.md
#include <signal.h>
#include <unistd.h>
diff --git a/tools/README.md b/tools/README.md
index a0c41eb79f..df4c6ef7d2 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -1,7 +1,5 @@
buildgen: template renderer for our build system.
-distpackages: script to generate debian packages.
-
distrib: scripts to distribute language-specific packages.
dockerfile: Docker files to test gRPC.
@@ -12,6 +10,4 @@ gce: scripts to help setup testing infrastructure on GCE.
jenkins: support for running tests on Jenkins.
-profile_analyzer: pretty printer for gRPC profiling data.
-
run_tests: scripts to run gRPC tests in parallel.
diff --git a/tools/run_tests/build_node.bat b/tools/run_tests/build_node.bat
index 6896bc1d1b..82e8208348 100644
--- a/tools/run_tests/build_node.bat
+++ b/tools/run_tests/build_node.bat
@@ -27,4 +27,16 @@
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-npm install --build-from-source \ No newline at end of file
+set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
+
+del /f /q BUILD || rmdir build /s /q
+
+call npm install --build-from-source
+
+@rem delete the redundant openssl headers
+for /f "delims=v" %%v in ('node --version') do (
+ rmdir "%USERPROFILE%\.node-gyp\%%v\include\node\openssl" /S /Q
+)
+
+@rem rebuild, because it probably failed the first time
+call npm install --build-from-source \ No newline at end of file
diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh
index e0fcbb602d..f120fc7ed6 100755
--- a/tools/run_tests/build_python.sh
+++ b/tools/run_tests/build_python.sh
@@ -45,3 +45,6 @@ export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
tox --notest
$ROOT/.tox/py27/bin/python $ROOT/setup.py build
+$ROOT/.tox/py27/bin/python $ROOT/setup.py build_py
+$ROOT/.tox/py27/bin/python $ROOT/setup.py build_ext --inplace
+$ROOT/.tox/py27/bin/python $ROOT/setup.py gather --test
diff --git a/tools/run_tests/post_test_node.bat b/tools/run_tests/post_test_node.bat
deleted file mode 100644
index 1a2a5491fa..0000000000
--- a/tools/run_tests/post_test_node.bat
+++ /dev/null
@@ -1,30 +0,0 @@
-@rem Copyright 2016, Google Inc.
-@rem All rights reserved.
-@rem
-@rem Redistribution and use in source and binary forms, with or without
-@rem modification, are permitted provided that the following conditions are
-@rem met:
-@rem
-@rem * Redistributions of source code must retain the above copyright
-@rem notice, this list of conditions and the following disclaimer.
-@rem * Redistributions in binary form must reproduce the above
-@rem copyright notice, this list of conditions and the following disclaimer
-@rem in the documentation and/or other materials provided with the
-@rem distribution.
-@rem * Neither the name of Google Inc. nor the names of its
-@rem contributors may be used to endorse or promote products derived from
-@rem this software without specific prior written permission.
-@rem
-@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-rmdir node_modules /S /Q \ No newline at end of file
diff --git a/tools/run_tests/pre_build_node.bat b/tools/run_tests/pre_build_node.bat
index 6e7cbe5d42..a29456f9ed 100644
--- a/tools/run_tests/pre_build_node.bat
+++ b/tools/run_tests/pre_build_node.bat
@@ -27,13 +27,8 @@
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-@rem Expire cache after 1 week
-npm update --cache-min 604800
+set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
-npm install node-gyp-install
-.\node_modules\.bin\node-gyp-install.cmd
+@rem Expire cache after 1 week
+call npm update --cache-min 604800
-@rem delete the redundant openssl headers
-for /f "delims=v" %%v in ('node --version') do (
- rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\%%v\include\node\openssl" /S /Q
-) \ No newline at end of file
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index df3ab90a83..1dc772a856 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -60,6 +60,8 @@ _SKIP_COMPRESSION = ['large_compressed_unary',
_SKIP_ADVANCED = ['custom_metadata', 'status_code_and_message',
'unimplemented_method']
+_TEST_TIMEOUT = 3*60
+
class CXXLanguage:
def __init__(self):
@@ -459,7 +461,7 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name,
environ=environ,
shortname='%s:%s:%s:%s' % (suite_name, server_host_name, language,
test_case),
- timeout_seconds=90,
+ timeout_seconds=_TEST_TIMEOUT,
flake_retries=5 if args.allow_flakes else 0,
timeout_retries=2 if args.allow_flakes else 0,
kill_handler=_job_kill_handler)
@@ -495,7 +497,7 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
environ=environ,
shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name,
test_case),
- timeout_seconds=90,
+ timeout_seconds=_TEST_TIMEOUT,
flake_retries=5 if args.allow_flakes else 0,
timeout_retries=2 if args.allow_flakes else 0,
kill_handler=_job_kill_handler)
diff --git a/tools/run_tests/run_node.bat b/tools/run_tests/run_node.bat
index 4177736356..0987fbee55 100644
--- a/tools/run_tests/run_node.bat
+++ b/tools/run_tests/run_node.bat
@@ -27,6 +27,7 @@
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
set JUNIT_REPORT_PATH=src\node\report.xml
set JUNIT_REPORT_STACK=1
.\node_modules\.bin\mocha.cmd --reporter mocha-jenkins-reporter --timeout 8000 src\node\test \ No newline at end of file
diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh
index ffe9c12af1..beb747a616 100755
--- a/tools/run_tests/run_python.sh
+++ b/tools/run_tests/run_python.sh
@@ -42,7 +42,12 @@ export LDFLAGS="-L$ROOT/libs/$CONFIG"
export GRPC_PYTHON_BUILD_WITH_CYTHON=1
export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
-tox
+if [ "$CONFIG" = "gcov" ]
+then
+ tox
+else
+ $ROOT/.tox/py27/bin/python $ROOT/setup.py test
+fi
mkdir -p $ROOT/reports
rm -rf $ROOT/reports/python-coverage
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 08a5ff0e8f..cc004f38d7 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -290,10 +290,7 @@ class NodeLanguage(object):
return [['tools/run_tests/build_node.sh', self.node_version]]
def post_tests_steps(self):
- if self.platform == 'windows':
- return [['tools\\run_tests\\post_test_node.bat']]
- else:
- return []
+ return []
def makefile_name(self):
return 'Makefile'
@@ -353,15 +350,27 @@ class PythonLanguage(object):
_check_compiler(self.args.compiler, ['default'])
def test_specs(self):
+ # load list of known test suites
+ with open('src/python/grpcio/tests/tests.json') as tests_json_file:
+ tests_json = json.load(tests_json_file)
environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
environment['PYVER'] = '2.7'
- return [self.config.job_spec(
- ['tools/run_tests/run_python.sh'],
- None,
- environ=environment,
- shortname='py.test',
- timeout_seconds=15*60
- )]
+ if self.config.build_config != 'gcov':
+ return [self.config.job_spec(
+ ['tools/run_tests/run_python.sh'],
+ None,
+ environ=dict(environment.items() +
+ [('GPRC_PYTHON_TESTRUNNER_FILTER', suite_name)]),
+ shortname='py.test.%s' % suite_name,
+ timeout_seconds=5*60)
+ for suite_name in tests_json]
+ else:
+ return [self.config.job_spec(['tools/run_tests/run_python.sh'],
+ None,
+ environ=environment,
+ shortname='py.test.coverage',
+ timeout_seconds=15*60)]
+
def pre_build_steps(self):
return []