Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F81296
D7552.diff
All Users
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
D7552.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -373,6 +373,7 @@
'phutil_safe_html' => 'markup/render.php',
'phutil_split_lines' => 'utils/utils.php',
'phutil_tag' => 'markup/render.php',
+ 'phutil_tag_div' => 'markup/render.php',
'phutil_unescape_uri_path_component' => 'markup/render.php',
'phutil_utf8_console_strlen' => 'utils/utf8.php',
'phutil_utf8_convert' => 'utils/utf8.php',
@@ -400,6 +401,7 @@
'vqsprintf' => 'xsprintf/qsprintf.php',
'vqueryfx' => 'xsprintf/queryfx.php',
'vqueryfx_all' => 'xsprintf/queryfx.php',
+ 'vurisprintf' => 'xsprintf/urisprintf.php',
'xhp_parser_node_constants' => 'parser/xhpast/parser_nodes.php',
'xhpast_get_binary_path' => 'parser/xhpast/bin/xhpast_parse.php',
'xhpast_get_build_instructions' => 'parser/xhpast/bin/xhpast_parse.php',
diff --git a/src/channel/PhutilChannel.php b/src/channel/PhutilChannel.php
--- a/src/channel/PhutilChannel.php
+++ b/src/channel/PhutilChannel.php
@@ -231,6 +231,14 @@
/**
+ * Close the channel for writing.
+ *
+ * @return void
+ * @task impl
+ */
+ abstract public function closeWriteChannel();
+
+ /**
* Test if the channel is open for reading.
*
* @return bool True if the channel is open for reading.
diff --git a/src/channel/PhutilChannelChannel.php b/src/channel/PhutilChannelChannel.php
--- a/src/channel/PhutilChannelChannel.php
+++ b/src/channel/PhutilChannelChannel.php
@@ -40,6 +40,10 @@
return $this->channel->isOpen();
}
+ public function closeWriteChannel() {
+ return $this->channel->closeWriteChannel();
+ }
+
public function isOpenForReading() {
return $this->channel->isOpenForReading();
}
diff --git a/src/channel/PhutilExecChannel.php b/src/channel/PhutilExecChannel.php
--- a/src/channel/PhutilExecChannel.php
+++ b/src/channel/PhutilExecChannel.php
@@ -108,6 +108,10 @@
$this->future->write($bytes, $keep_pipe = true);
}
+ public function closeWriteChannel() {
+ $this->future->write('', $keep_pipe = false);
+ }
+
protected function writeBytes($bytes) {
throw new Exception("ExecFuture can not write bytes directly!");
}
diff --git a/src/channel/PhutilProtocolChannel.php b/src/channel/PhutilProtocolChannel.php
--- a/src/channel/PhutilProtocolChannel.php
+++ b/src/channel/PhutilProtocolChannel.php
@@ -121,11 +121,17 @@
* @task wait
*/
public function waitForMessage() {
- while ($this->update()) {
+ while (true) {
+ $is_open = $this->update();
$message = $this->read();
if ($message !== null) {
return $message;
}
+
+ if (!$is_open) {
+ break;
+ }
+
self::waitForAny(array($this));
}
diff --git a/src/channel/PhutilSocketChannel.php b/src/channel/PhutilSocketChannel.php
--- a/src/channel/PhutilSocketChannel.php
+++ b/src/channel/PhutilSocketChannel.php
@@ -173,6 +173,10 @@
}
}
+ public function closeWriteChannel() {
+ $this->closeWriteSocket();
+ }
+
private function closeOneSocket($socket) {
if (!$socket) {
return;
diff --git a/src/channel/__tests__/PhutilPHPObjectProtocolChannelTestCase.php b/src/channel/__tests__/PhutilPHPObjectProtocolChannelTestCase.php
--- a/src/channel/__tests__/PhutilPHPObjectProtocolChannelTestCase.php
+++ b/src/channel/__tests__/PhutilPHPObjectProtocolChannelTestCase.php
@@ -26,4 +26,41 @@
"Objects are not the same.");
}
+ public function testCloseSocketWriteChannel() {
+ list($x, $y) = PhutilSocketChannel::newChannelPair();
+ $xp = new PhutilPHPObjectProtocolChannel($x);
+ $yp = new PhutilPHPObjectProtocolChannel($y);
+
+ $yp->closeWriteChannel();
+ $yp->update();
+
+ // NOTE: This test is more broad than the implementation needs to be. A
+ // better test would be to verify that this throws an exception:
+ //
+ // $xp->waitForMessage();
+ //
+ // However, if the test breaks, that method will hang forever instead of
+ // returning, which would be hard to diagnose. Since the current
+ // implementation shuts down the entire channel, just test for that.
+
+ $this->assertEqual(false, $xp->update(), 'Expected channel to close.');
+ }
+
+ public function testCloseExecWriteChannel() {
+ $future = new ExecFuture('cat');
+
+ // If this test breaks, we want to explode, not hang forever.
+ $future->setTimeout(5);
+
+ $exec_channel = new PhutilExecChannel($future);
+ $exec_channel->write("quack");
+ $exec_channel->closeWriteChannel();
+
+ // If `closeWriteChannel()` did what it is supposed to, this will just
+ // echo "quack" and exit with no error code. If the channel did not close,
+ // this will time out after 5 seconds and throw.
+ $future->resolvex();
+ }
+
+
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/nd/oi/qdc5pvilubjyfpoy
Default Alt Text
D7552.diff (4 KB)
Attached To
Mode
D7552: Allow PhutilChannels to have their write channels closed explicitly
Attached
Detach File
Event Timeline
Log In to Comment