aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Stanley Cheung <stanleycheung@google.com>2017-08-24 12:28:14 -0700
committerGravatar Stanley Cheung <stanleycheung@google.com>2017-08-24 12:28:14 -0700
commitabbeefa8a462530b29f2341bd798c6f3f47f1350 (patch)
tree39a5fc00a2bdf3221cc099387895c591cedd1e53
parentdcbd142bd199f76ae6725f11e7de1457d39d8545 (diff)
PHP: backport master features into v1.6.x branch
-rw-r--r--package.xml12
-rw-r--r--src/php/ext/grpc/call_credentials.c2
-rw-r--r--src/php/ext/grpc/channel.c40
-rw-r--r--src/php/ext/grpc/channel_credentials.c8
-rw-r--r--src/php/ext/grpc/php_grpc.c42
-rw-r--r--src/php/ext/grpc/php_grpc.h6
-rw-r--r--src/php/lib/Grpc/ServerStreamingCall.php28
-rw-r--r--src/php/lib/Grpc/UnaryCall.php28
-rw-r--r--src/php/tests/unit_tests/ChannelTest.php15
-rw-r--r--templates/package.xml.template12
10 files changed, 124 insertions, 69 deletions
diff --git a/package.xml b/package.xml
index c970a918d2..ce67849273 100644
--- a/package.xml
+++ b/package.xml
@@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2017-05-22</date>
+ <date>2017-08-24</date>
<time>16:06:07</time>
<version>
<release>1.6.0RC1</release>
@@ -22,13 +22,9 @@
</stability>
<license>Apache 2.0</license>
<notes>
-- Fixed some memory leaks #9559, #10996
-- Disabled cares dependency from gRPC C Core #10940
-- De-coupled protobuf dependency #11112
-- Fixed extension reported version #10842
-- Added config.w32 for Windows support #8161
-- Fixed PHP distrib test after cc files were added #11193
-- Fixed protoc plugin comment escape bug #11025
+- License changed to Apache 2.0
+- Added support for php_namespace option in codegen plugin #11886
+- Updated gRPC C Core library version 1.6
</notes>
<contents>
<dir baseinstalldir="/" name="/">
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index f46091d709..1eee8645df 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -179,7 +179,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
grpc_metadata_array metadata;
bool cleanup = true;
- if (Z_TYPE_P(retval) != IS_ARRAY) {
+ if (retval == NULL || Z_TYPE_P(retval) != IS_ARRAY) {
cleanup = false;
code = GRPC_STATUS_INVALID_ARGUMENT;
} else if (!create_metadata_array(retval, &metadata)) {
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index f1187e8722..dc3acc89bb 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -66,6 +66,8 @@ PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), p->wrapper->key,
key_len, rsrc))) {
grpc_channel_destroy(p->wrapper->wrapped);
+ free(p->wrapper->target);
+ free(p->wrapper->args_hashstr);
}
gpr_mu_unlock(&global_persistent_list_mu);
}
@@ -158,7 +160,7 @@ void create_and_add_channel_to_persistent_list(
grpc_channel_args args,
wrapped_grpc_channel_credentials *creds,
char *key,
- php_grpc_int key_len) {
+ php_grpc_int key_len TSRMLS_DC) {
php_grpc_zend_resource new_rsrc;
channel_persistent_le_t *le;
// this links each persistent list entry to a destructor
@@ -187,10 +189,8 @@ void create_and_add_channel_to_persistent_list(
* credentials.
*
* If the $args array contains a "force_new" key mapping to a boolean value
- * of "true", a new underlying grpc_channel will be created regardless. If
- * there are any opened channels on the same hostname, user must manually
- * call close() on those dangling channels before the end of the PHP
- * script.
+ * of "true", a new and separate underlying grpc_channel will be created
+ * and returned. This will not affect existing channels.
*
* @param string $target The hostname to associate with this channel
* @param array $args_array The arguments to pass to the Channel
@@ -273,19 +273,15 @@ PHP_METHOD(Channel, __construct) {
}
channel->wrapper = malloc(sizeof(grpc_channel_wrapper));
channel->wrapper->key = key;
- channel->wrapper->target = target;
- channel->wrapper->args_hashstr = sha1str;
+ channel->wrapper->target = strdup(target);
+ channel->wrapper->args_hashstr = strdup(sha1str);
if (creds != NULL && creds->hashstr != NULL) {
channel->wrapper->creds_hashstr = creds->hashstr;
}
gpr_mu_init(&channel->wrapper->mu);
smart_str_free(&buf);
- if (force_new) {
- php_grpc_delete_persistent_list_entry(key, key_len TSRMLS_CC);
- }
-
- if (creds != NULL && creds->has_call_creds) {
+ if (force_new || (creds != NULL && creds->has_call_creds)) {
// If the ChannelCredentials object was composed with a CallCredentials
// object, there is no way we can tell them apart. Do NOT persist
// them. They should be individually destroyed.
@@ -293,7 +289,7 @@ PHP_METHOD(Channel, __construct) {
} else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), key,
key_len, rsrc))) {
create_and_add_channel_to_persistent_list(
- channel, target, args, creds, key, key_len);
+ channel, target, args, creds, key, key_len TSRMLS_CC);
} else {
// Found a previously stored channel in the persistent list
channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
@@ -303,7 +299,7 @@ PHP_METHOD(Channel, __construct) {
strcmp(creds->hashstr, le->channel->creds_hashstr) != 0)) {
// somehow hash collision
create_and_add_channel_to_persistent_list(
- channel, target, args, creds, key, key_len);
+ channel, target, args, creds, key, key_len TSRMLS_CC);
} else {
channel->wrapper = le->channel;
}
@@ -416,12 +412,14 @@ PHP_METHOD(Channel, close) {
gpr_mu_lock(&channel->wrapper->mu);
if (channel->wrapper->wrapped != NULL) {
grpc_channel_destroy(channel->wrapper->wrapped);
+ free(channel->wrapper->target);
+ free(channel->wrapper->args_hashstr);
channel->wrapper->wrapped = NULL;
- }
- php_grpc_delete_persistent_list_entry(channel->wrapper->key,
- strlen(channel->wrapper->key)
- TSRMLS_CC);
+ php_grpc_delete_persistent_list_entry(channel->wrapper->key,
+ strlen(channel->wrapper->key)
+ TSRMLS_CC);
+ }
gpr_mu_unlock(&channel->wrapper->mu);
}
@@ -449,12 +447,11 @@ static void php_grpc_channel_plink_dtor(php_grpc_zend_resource *rsrc
gpr_mu_lock(&le->channel->mu);
if (le->channel->wrapped != NULL) {
grpc_channel_destroy(le->channel->wrapped);
- free(le->channel->key);
- free(le->channel);
+ free(le->channel->target);
+ free(le->channel->args_hashstr);
}
gpr_mu_unlock(&le->channel->mu);
}
- free(le);
}
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
@@ -496,6 +493,7 @@ GRPC_STARTUP_FUNCTION(channel) {
INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods);
ce.create_object = create_wrapped_grpc_channel;
grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC);
+ gpr_mu_init(&global_persistent_list_mu);
le_plink = zend_register_list_destructors_ex(
NULL, php_grpc_channel_plink_dtor, "Persistent Channel", module_number);
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index 19e1cefb6f..86e4f46c67 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -135,6 +135,8 @@ PHP_METHOD(ChannelCredentials, createSsl) {
pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL;
+ grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
+
/* "|s!s!s!" == 3 optional nullable strings */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!",
&pem_root_certs, &root_certs_length,
@@ -148,7 +150,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
}
php_grpc_int hashkey_len = root_certs_length + cert_chain_length;
- char hashkey[hashkey_len];
+ char *hashkey = emalloc(hashkey_len);
if (root_certs_length > 0) {
strcpy(hashkey, pem_root_certs);
}
@@ -164,6 +166,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, hashstr, false
TSRMLS_CC);
+ efree(hashkey);
RETURN_DESTROY_ZVAL(creds_object);
}
@@ -177,6 +180,8 @@ PHP_METHOD(ChannelCredentials, createComposite) {
zval *cred1_obj;
zval *cred2_obj;
+ grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
+
/* "OO" == 2 Objects */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj,
grpc_ce_channel_credentials, &cred2_obj,
@@ -245,7 +250,6 @@ void grpc_init_channel_credentials(TSRMLS_D) {
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "Grpc\\ChannelCredentials",
channel_credentials_methods);
- grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
ce.create_object = create_wrapped_grpc_channel_credentials;
grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC);
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel_credentials,
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index a96daf7d9b..4ed56de993 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -34,7 +34,8 @@
#include <ext/standard/info.h>
#include "php_grpc.h"
-// ZEND_DECLARE_MODULE_GLOBALS(grpc)
+ZEND_DECLARE_MODULE_GLOBALS(grpc)
+static PHP_GINIT_FUNCTION(grpc);
/* {{{ grpc_functions[]
*
@@ -55,13 +56,17 @@ zend_module_entry grpc_module_entry = {
grpc_functions,
PHP_MINIT(grpc),
PHP_MSHUTDOWN(grpc),
- NULL,
+ PHP_RINIT(grpc),
NULL,
PHP_MINFO(grpc),
#if ZEND_MODULE_API_NO >= 20010901
PHP_GRPC_VERSION,
#endif
- STANDARD_MODULE_PROPERTIES};
+ PHP_MODULE_GLOBALS(grpc),
+ PHP_GINIT(grpc),
+ NULL,
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX};
/* }}} */
#ifdef COMPILE_DL_GRPC
@@ -99,7 +104,6 @@ PHP_MINIT_FUNCTION(grpc) {
REGISTER_INI_ENTRIES();
*/
/* Register call error constants */
- grpc_init();
REGISTER_LONG_CONSTANT("Grpc\\CALL_OK", GRPC_CALL_OK,
CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("Grpc\\CALL_ERROR", GRPC_CALL_ERROR,
@@ -227,7 +231,6 @@ PHP_MINIT_FUNCTION(grpc) {
grpc_init_channel_credentials(TSRMLS_C);
grpc_init_call_credentials(TSRMLS_C);
grpc_init_server_credentials(TSRMLS_C);
- grpc_php_init_completion_queue(TSRMLS_C);
return SUCCESS;
}
/* }}} */
@@ -240,9 +243,12 @@ PHP_MSHUTDOWN_FUNCTION(grpc) {
*/
// WARNING: This function IS being called by PHP when the extension
// is unloaded but the logs were somehow suppressed.
- grpc_shutdown_timeval(TSRMLS_C);
- grpc_php_shutdown_completion_queue(TSRMLS_C);
- grpc_shutdown();
+ if (GRPC_G(initialized)) {
+ grpc_shutdown_timeval(TSRMLS_C);
+ grpc_php_shutdown_completion_queue(TSRMLS_C);
+ grpc_shutdown();
+ GRPC_G(initialized) = 0;
+ }
return SUCCESS;
}
/* }}} */
@@ -259,6 +265,26 @@ PHP_MINFO_FUNCTION(grpc) {
*/
}
/* }}} */
+
+/* {{{ PHP_RINIT_FUNCTION
+ */
+PHP_RINIT_FUNCTION(grpc) {
+ if (!GRPC_G(initialized)) {
+ grpc_init();
+ grpc_php_init_completion_queue(TSRMLS_C);
+ GRPC_G(initialized) = 1;
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_GINIT_FUNCTION
+ */
+static PHP_GINIT_FUNCTION(grpc) {
+ grpc_globals->initialized = 0;
+}
+/* }}} */
+
/* The previous line is meant for vim and emacs, so it can correctly fold and
unfold functions in source code. See the corresponding marks just before
function definition, where the functions purpose is also documented. Please
diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h
index 32329178dc..e30f011c39 100644
--- a/src/php/ext/grpc/php_grpc.h
+++ b/src/php/ext/grpc/php_grpc.h
@@ -49,14 +49,16 @@ PHP_MINIT_FUNCTION(grpc);
PHP_MSHUTDOWN_FUNCTION(grpc);
/* Displays information about the module */
PHP_MINFO_FUNCTION(grpc);
+/* Code that runs at request start */
+PHP_RINIT_FUNCTION(grpc);
/*
Declare any global variables you may need between the BEGIN
and END macros here:
-
+*/
ZEND_BEGIN_MODULE_GLOBALS(grpc)
+ zend_bool initialized;
ZEND_END_MODULE_GLOBALS(grpc)
-*/
/* In every utility function you add that needs to use variables
in php_grpc_globals, call TSRMLS_FETCH(); after declaring other
diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php
index 269a99ab59..f8fddfea01 100644
--- a/src/php/lib/Grpc/ServerStreamingCall.php
+++ b/src/php/lib/Grpc/ServerStreamingCall.php
@@ -40,13 +40,11 @@ class ServerStreamingCall extends AbstractCall
if (array_key_exists('flags', $options)) {
$message_array['flags'] = $options['flags'];
}
- $event = $this->call->startBatch([
+ $this->call->startBatch([
OP_SEND_INITIAL_METADATA => $metadata,
- OP_RECV_INITIAL_METADATA => true,
OP_SEND_MESSAGE => $message_array,
OP_SEND_CLOSE_FROM_CLIENT => true,
]);
- $this->metadata = $event->metadata;
}
/**
@@ -54,9 +52,15 @@ class ServerStreamingCall extends AbstractCall
*/
public function responses()
{
- $response = $this->call->startBatch([
- OP_RECV_MESSAGE => true,
- ])->message;
+ $batch = [OP_RECV_MESSAGE => true];
+ if ($this->metadata === null) {
+ $batch[OP_RECV_INITIAL_METADATA] = true;
+ }
+ $read_event = $this->call->startBatch($batch);
+ if ($this->metadata === null) {
+ $this->metadata = $read_event->metadata;
+ }
+ $response = $read_event->message;
while ($response !== null) {
yield $this->_deserializeResponse($response);
$response = $this->call->startBatch([
@@ -81,4 +85,16 @@ class ServerStreamingCall extends AbstractCall
return $status_event->status;
}
+
+ /**
+ * @return mixed The metadata sent by the server
+ */
+ public function getMetadata()
+ {
+ if ($this->metadata === null) {
+ $event = $this->call->startBatch([OP_RECV_INITIAL_METADATA => true]);
+ $this->metadata = $event->metadata;
+ }
+ return $this->metadata;
+ }
}
diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php
index dd55d02165..e8496492b8 100644
--- a/src/php/lib/Grpc/UnaryCall.php
+++ b/src/php/lib/Grpc/UnaryCall.php
@@ -40,13 +40,11 @@ class UnaryCall extends AbstractCall
if (isset($options['flags'])) {
$message_array['flags'] = $options['flags'];
}
- $event = $this->call->startBatch([
+ $this->call->startBatch([
OP_SEND_INITIAL_METADATA => $metadata,
- OP_RECV_INITIAL_METADATA => true,
OP_SEND_MESSAGE => $message_array,
OP_SEND_CLOSE_FROM_CLIENT => true,
]);
- $this->metadata = $event->metadata;
}
/**
@@ -56,14 +54,32 @@ class UnaryCall extends AbstractCall
*/
public function wait()
{
- $event = $this->call->startBatch([
+ $batch = [
OP_RECV_MESSAGE => true,
OP_RECV_STATUS_ON_CLIENT => true,
- ]);
-
+ ];
+ if ($this->metadata === null) {
+ $batch[OP_RECV_INITIAL_METADATA] = true;
+ }
+ $event = $this->call->startBatch($batch);
+ if ($this->metadata === null) {
+ $this->metadata = $event->metadata;
+ }
$status = $event->status;
$this->trailing_metadata = $status->metadata;
return [$this->_deserializeResponse($event->message), $status];
}
+
+ /**
+ * @return mixed The metadata sent by the server
+ */
+ public function getMetadata()
+ {
+ if ($this->metadata === null) {
+ $event = $this->call->startBatch([OP_RECV_INITIAL_METADATA => true]);
+ $this->metadata = $event->metadata;
+ }
+ return $this->metadata;
+ }
}
diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php
index 400df0fb66..c375a16269 100644
--- a/src/php/tests/unit_tests/ChannelTest.php
+++ b/src/php/tests/unit_tests/ChannelTest.php
@@ -517,8 +517,6 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
- // any dangling old connection to the same host must be
- // manually closed
$this->channel1->close();
$this->channel2->close();
}
@@ -529,6 +527,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$this->channel1 = new Grpc\Channel('localhost:1', []);
$this->channel2 = new Grpc\Channel('localhost:1',
["force_new" => true]);
+ // channel3 shares with channel1
$this->channel3 = new Grpc\Channel('localhost:1', []);
// try to connect on channel2
@@ -540,29 +539,31 @@ class ChannelTest extends PHPUnit_Framework_TestCase
$state = $this->channel2->getConnectivityState();
$this->assertConnecting($state);
$state = $this->channel3->getConnectivityState();
- $this->assertConnecting($state);
+ $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
$this->channel1->close();
$this->channel2->close();
}
+ /**
+ * @expectedException RuntimeException
+ */
public function testPersistentChannelForceNewOldChannelClose()
{
$this->channel1 = new Grpc\Channel('localhost:1', []);
$this->channel2 = new Grpc\Channel('localhost:1',
["force_new" => true]);
+ // channel3 shares with channel1
$this->channel3 = new Grpc\Channel('localhost:1', []);
$this->channel1->close();
$state = $this->channel2->getConnectivityState();
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
- $state = $this->channel3->getConnectivityState();
- $this->assertEquals(GRPC\CHANNEL_IDLE, $state);
- $this->channel2->close();
- $this->channel3->close();
+ // channel3 already closed
+ $state = $this->channel3->getConnectivityState();
}
public function testPersistentChannelForceNewNewChannelClose()
diff --git a/templates/package.xml.template b/templates/package.xml.template
index 27cc4d01a9..a378b58e0c 100644
--- a/templates/package.xml.template
+++ b/templates/package.xml.template
@@ -12,7 +12,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2017-05-22</date>
+ <date>2017-08-24</date>
<time>16:06:07</time>
<version>
<release>${settings.php_version.php()}</release>
@@ -24,13 +24,9 @@
</stability>
<license>Apache 2.0</license>
<notes>
- - Fixed some memory leaks #9559, #10996
- - Disabled cares dependency from gRPC C Core #10940
- - De-coupled protobuf dependency #11112
- - Fixed extension reported version #10842
- - Added config.w32 for Windows support #8161
- - Fixed PHP distrib test after cc files were added #11193
- - Fixed protoc plugin comment escape bug #11025
+ - License changed to Apache 2.0
+ - Added support for php_namespace option in codegen plugin #11886
+ - Updated gRPC C Core library version 1.6
</notes>
<contents>
<dir baseinstalldir="/" name="/">