1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-28 17:52:42 +01:00

Fix three Windows subprocess issues

Summary:
Fixes T13504. This fixes three issues:

  # In ExecFuture, "proc_open()" on an invalid binary could fail with an unconditional exception.
  # In ExecPassthru, "proc_open()" on an invalid binary could fail with an unconditional exception.
  # In "arc browse", "start <url>" does not work when the shell is bypassed.

In (1) and (2), the desired behavior is to fail with an exit code which is sometimes upgraded to an exception depending on calling convention.

Issue (1) most commonly manifested as "find" failing when run via "cmd.exe".

Issue (2) most commonly manifested as "arc browse" failing.

Issue (3) was entangled with issue (2).

In cases (1) and (2), assume "proc_open()" failures under Windows are because of bad binaries and treat them like bogus commands on Linux/Mac.

In case (3), use "cmd /c start" instead of "start" as a default browser on Windows.

Test Plan:
  - On Windows, did mime type detection in cmd.exe. Before patch: proc_open() exception in "find". After patch: clean (albeit not terribly useful) detection.
  - On Windows, did "arc browse ...". Before patch: proc_open() exception in "start". After patch: clean browser execution.

Maniphest Tasks: T13504

Differential Revision: https://secure.phabricator.com/D21047
This commit is contained in:
epriestley 2020-04-01 15:59:20 -07:00
parent 492113370a
commit 63276697eb
3 changed files with 51 additions and 22 deletions

View file

@ -605,6 +605,9 @@ final class ExecFuture extends PhutilExecutableFuture {
$trap->destroy(); $trap->destroy();
} else { } else {
$err = error_get_last(); $err = error_get_last();
if ($err) {
$err = $err['message'];
}
} }
if ($is_windows) { if ($is_windows) {
@ -618,18 +621,21 @@ final class ExecFuture extends PhutilExecutableFuture {
// it fails to resolve the command. // it fails to resolve the command.
// When you run an invalid command on a Windows system, we bypass the // When you run an invalid command on a Windows system, we bypass the
// shell and the "proc_open()" itself fails. Throw a "CommandException" // shell and the "proc_open()" itself fails. See also T13504. Fail the
// here for consistency with the Linux behavior in this common failure // future immediately, acting as though it exited with an error code
// case. // for consistency with Linux.
throw new CommandException( $result = array(
1,
'',
pht( pht(
'Call to "proc_open()" to open a subprocess failed: %s', 'Call to "proc_open()" to open a subprocess failed: %s',
$err), $err),
$this->getCommand(), );
1,
'', $this->setResult($result);
'');
return true;
} }
if ($is_windows) { if ($is_windows) {

View file

@ -68,15 +68,22 @@ final class PhutilExecPassthru extends PhutilExecutableFuture {
$trap->destroy(); $trap->destroy();
if (!is_resource($proc)) { if (!is_resource($proc)) {
throw new Exception( // See T13504. When "proc_open()" is given a command with a binary
pht( // that isn't available on Windows with "bypass_shell", the function
'Failed to passthru %s: %s', // fails entirely.
'proc_open()', if (phutil_is_windows()) {
$errors)); $err = 1;
} else {
throw new Exception(
pht(
'Failed to passthru %s: %s',
'proc_open()',
$errors));
}
} else {
$err = proc_close($proc);
} }
$err = proc_close($proc);
return $err; return $err;
} }

View file

@ -2069,13 +2069,19 @@ abstract class ArcanistWorkflow extends Phobject {
protected function openURIsInBrowser(array $uris) { protected function openURIsInBrowser(array $uris) {
$browser = $this->getBrowserCommand(); $browser = $this->getBrowserCommand();
// The "browser" may actually be a list of arguments.
if (!is_array($browser)) {
$browser = array($browser);
}
foreach ($uris as $uri) { foreach ($uris as $uri) {
$err = phutil_passthru('%s %s', $browser, $uri); $err = phutil_passthru('%LR %R', $browser, $uri);
if ($err) { if ($err) {
throw new ArcanistUsageException( throw new ArcanistUsageException(
pht( pht(
"Failed to open '%s' in browser ('%s'). ". 'Failed to open URI "%s" in browser ("%s"). '.
"Check your 'browser' config option.", 'Check your "browser" config option.',
$uri, $uri,
$browser)); $browser));
} }
@ -2089,19 +2095,29 @@ abstract class ArcanistWorkflow extends Phobject {
} }
if (phutil_is_windows()) { if (phutil_is_windows()) {
return 'start'; // See T13504. We now use "bypass_shell", so "start" alone is no longer
// a valid binary to invoke directly.
return array(
'cmd',
'/c',
'start',
);
} }
$candidates = array('sensible-browser', 'xdg-open', 'open'); $candidates = array(
'sensible-browser' => array('sensible-browser'),
'xdg-open' => array('xdg-open'),
'open' => array('open', '--'),
);
// NOTE: The "open" command works well on OS X, but on many Linuxes "open" // NOTE: The "open" command works well on OS X, but on many Linuxes "open"
// exists and is not a browser. For now, we're just looking for other // exists and is not a browser. For now, we're just looking for other
// commands first, but we might want to be smarter about selecting "open" // commands first, but we might want to be smarter about selecting "open"
// only on OS X. // only on OS X.
foreach ($candidates as $cmd) { foreach ($candidates as $cmd => $argv) {
if (Filesystem::binaryExists($cmd)) { if (Filesystem::binaryExists($cmd)) {
return $cmd; return $argv;
} }
} }