Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14845580
D21666.id.diff
No One
Temporary
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
D21666.id.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
@@ -378,6 +378,7 @@
'ArcanistNoParentScopeXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNoParentScopeXHPASTLinterRule.php',
'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNoParentScopeXHPASTLinterRuleTestCase.php',
'ArcanistNoURIConduitException' => 'conduit/ArcanistNoURIConduitException.php',
+ 'ArcanistNonblockingGuard' => 'utils/ArcanistNonblockingGuard.php',
'ArcanistNoneLintRenderer' => 'lint/renderer/ArcanistNoneLintRenderer.php',
'ArcanistObjectListHardpoint' => 'hardpoint/ArcanistObjectListHardpoint.php',
'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistObjectOperatorSpacingXHPASTLinterRule.php',
@@ -1434,6 +1435,7 @@
'ArcanistNoParentScopeXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistNoURIConduitException' => 'ArcanistConduitException',
+ 'ArcanistNonblockingGuard' => 'Phobject',
'ArcanistNoneLintRenderer' => 'ArcanistLintRenderer',
'ArcanistObjectListHardpoint' => 'ArcanistHardpoint',
'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
diff --git a/src/toolset/ArcanistPrompt.php b/src/toolset/ArcanistPrompt.php
--- a/src/toolset/ArcanistPrompt.php
+++ b/src/toolset/ArcanistPrompt.php
@@ -93,16 +93,9 @@
// NOTE: We're making stdin nonblocking so that we can respond to signals
// immediately. If we don't, and you ^C during a prompt, the program does
- // not handle the signal until fgets() returns.
+ // not handle the signal until fgets() returns. See also T13649.
- // On Windows, we skip this because stdin can not be made nonblocking.
-
- if (!phutil_is_windows()) {
- $ok = stream_set_blocking($stdin, false);
- if (!$ok) {
- throw new Exception(pht('Unable to set stdin nonblocking.'));
- }
- }
+ $guard = ArcanistNonblockingGuard::newForStream($stdin);
echo "\n";
@@ -123,7 +116,7 @@
$is_saved = false;
- if (phutil_is_windows()) {
+ if (!$guard->getIsNonblocking()) {
$response = fgets($stdin);
} else {
while (true) {
diff --git a/src/utils/ArcanistNonblockingGuard.php b/src/utils/ArcanistNonblockingGuard.php
new file mode 100644
--- /dev/null
+++ b/src/utils/ArcanistNonblockingGuard.php
@@ -0,0 +1,56 @@
+<?php
+
+final class ArcanistNonblockingGuard
+ extends Phobject {
+
+ private $stream;
+ private $didSetNonblocking;
+
+ public static function newForStream($stream) {
+ $guard = new self();
+ $guard->stream = $stream;
+
+ if (phutil_is_windows()) {
+
+ // On Windows, we skip this because stdin can not be made nonblocking.
+
+ } else if (!function_exists('pcntl_signal')) {
+
+ // If we can't handle signals, we: can't reset the flag if we're
+ // interrupted; but also don't benefit from setting it in the first
+ // place since it's only relevant for handling interrupts during
+ // prompts. So just skip this.
+
+ } else {
+
+ // See T13649. Note that the "blocked" key identifies whether the
+ // stream is blocking or nonblocking, not whether it will block when
+ // read or written.
+
+ $metadata = stream_get_meta_data($stream);
+ $is_blocking = idx($metadata, 'blocked');
+ if ($is_blocking) {
+ $ok = stream_set_blocking($stream, false);
+ if (!$ok) {
+ throw new Exception(pht('Unable to set stream nonblocking.'));
+ }
+ $guard->didSetNonblocking = true;
+ }
+ }
+
+ return $guard;
+ }
+
+ public function getIsNonblocking() {
+ return $this->didSetNonblocking;
+ }
+
+ public function __destruct() {
+ if ($this->stream && $this->didSetNonblocking) {
+ stream_set_blocking($this->stream, true);
+ }
+
+ $this->stream = null;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 3, 11:53 PM (5 h, 2 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7088103
Default Alt Text
D21666.id.diff (4 KB)
Attached To
Mode
D21666: Avoid leaving stdin in nonblocking mode after a modern prompt
Attached
Detach File
Event Timeline
Log In to Comment