Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Unix: make UseShellExecute execute executables #33052

Merged
merged 19 commits into from Dec 5, 2018

Conversation

tmds
Copy link
Member

@tmds tmds commented Oct 25, 2018

On Windows, UseShellExecute executes executables. This gives it the same behavior on Unix.

This implements improvements discussed in https://github.com/dotnet/corefx/issues/24704.

CC @TSlivede @krwq @wtgodbe @rmunn @danmosemsft @omajid @marek-safar @wfurt @stephentoub

On Windows, UseShellExecute executes executables.
This gives it the same behavior on Unix.
@tmds tmds changed the title Unix: make UseShellExecute execute executables WIP Unix: make UseShellExecute execute executables Oct 25, 2018
@TSlivede
Copy link

TSlivede commented Oct 28, 2018

On Windows, UseShellExecute executes executables.

This is only true if ProcessStartInfo.Verb is null, "", or "open".
As I mentioned here, UseShellExecute can do all sorts of things, depending on the value of Verb. (If UseShellExecute is false, then Verb is ignored AFAIK). If Verb has a value that Windows doesn't understand, an Exception is thrown.


This gives it the same behavior on Unix.

To behave the same as on Windows:
If UseShellExecute is true, we should check the value of Verb.

  • If it is null, "", or "open", the code that tries to execute or open files (currently lines 308..336 in Process.Unix.cs in your PR) is used.
  • If it is "runas", "edit", "print" or some other known typical value for Verb, we could throw a "not (yet?) implemented" or "platform not supported" exception. (Or maybe we don't test this...?)
  • If it is something else, we throw the same exception that is used on Windows for unknown values of Verb.

@krwq
Copy link
Member

krwq commented Oct 29, 2018

It would be useful to add some test cases for this

@tmds tmds changed the title WIP Unix: make UseShellExecute execute executables Unix: make UseShellExecute execute executables Nov 6, 2018
@tmds
Copy link
Member Author

tmds commented Nov 6, 2018

This is ready for review.

@TSlivede
Copy link

TSlivede commented Nov 6, 2018

First of all: Thanks for implementing this!


Sorry, that I didn't notice this earlier, but on Windows Verb is matched case insensitive, so "Open" or even "oPeN" should also be accepted...


Just nitpicking: I do see advantages of moving the check of Verb into its own method (the constants "", open, etc. can be moved into a private field, so there are no "magic constants" within the code). However I think this reduces code readability and more importantly basically does a double negation of the logic behind Verb IMHO:
Instead of selecting the correct action based on the value of Verb and throwing an error for unknown values, the current implementation executes the "open"-Code if no exception was thrown because !IsValidVerb(startInfo.Verb) was false.

It's also hard to add Code for other values of Verb in the current implementation.

I've added a code suggestion as a review.

Copy link

@TSlivede TSlivede left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestions below only make sense together, not one comment alone.

Reasons for this suggestion in my comment.

@tmds
Copy link
Member Author

tmds commented Nov 7, 2018

I'm going to extend this PR with the WorkingDirectory behavior for UseShellExecute (and add a test for it):

When UseShellExecute is true, the WorkingDirectory property specifies the location of the executable. If WorkingDirectory is an empty string, the current directory is understood to contain the executable.

@tmds
Copy link
Member Author

tmds commented Nov 8, 2018

Unrelated CI fail, Linux arm64 Release Build, Ubuntu.1604.Arm64.Open-arm64:

System.Net.NameResolution.Tests.GetHostByNameTest
 DnsObsoleteBeginEndGetHostByName_EmptyString_ReturnsHostName
 DnsObsoleteGetHostByName_EmptyString_ReturnsHostName
System.Net.NameResolution.Tests.GetHostEntryTest
 Dns_GetHostEntryAsync_HostString_Ok(hostName: \"\")
 Dns_GetHostEntry_HostString_Ok(hostName: \"\")

@krwq
Copy link
Member

krwq commented Nov 21, 2018

@tmds lgtm - I think the verb check might have been correct in the first version (negated logic got me confused) - sorry for confusion

Copy link
Member

@krwq krwq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after reverting verb check to !string.IsNullOrEmpty(verb)

@tmds
Copy link
Member Author

tmds commented Nov 22, 2018

Looking at the build logs, it's not clear why some things failed.
One clear error message:

09:13:14 Fatal error in IL Linker
09:13:14 System.InvalidOperationException: Operation is not valid due to the current state of the object.
09:13:14    at Mono.Collections.Generic.Collection`1.Enumerator.CheckState()
09:13:14    at Mono.Collections.Generic.Collection`1.Enumerator.MoveNext()
09:13:14    at Mono.Linker.TypeReferenceExtensions.GetMethods(TypeReference type)+MoveNext()
09:13:14    at Mono.Linker.Steps.TypeMapStep.TryMatchMethod(TypeReference type, MethodDefinition method)
09:13:14    at Mono.Linker.Steps.TypeMapStep.GetBaseMethodInTypeHierarchy(TypeDefinition type, MethodDefinition method)
09:13:14    at Mono.Linker.Steps.TypeMapStep.GetBaseMethodInTypeHierarchy(MethodDefinition method)
09:13:14    at Mono.Linker.Steps.TypeMapStep.MapVirtualBaseMethod(MethodDefinition method)
09:13:14    at Mono.Linker.Steps.TypeMapStep.MapVirtualMethod(MethodDefinition method)
09:13:14    at Mono.Linker.Steps.TypeMapStep.MapVirtualMethods(TypeDefinition type)
09:13:14    at Mono.Linker.Steps.TypeMapStep.MapType(TypeDefinition type)
09:13:14    at Mono.Linker.Steps.TypeMapStep.ProcessAssembly(AssemblyDefinition assembly)
09:13:14    at Mono.Linker.Steps.BaseStep.Process(LinkContext context)
09:13:14    at Mono.Linker.Pipeline.Process(LinkContext context)
09:13:14    at Mono.Linker.Driver.Run(ILogger customLogger)
09:13:14    at Mono.Linker.Driver.Execute(String[] args, ILogger customLogger)
09:13:14   System.Linq -> /mnt/j/workspace/dotnet_corefx/master/linux-

@dotnet-bot Test Linux arm64 Release Build please
@dotnet-bot Test Linux x64 Release Build please

LGTM after reverting verb check to !string.IsNullOrEmpty(verb)

The verb != string.Empty that is in the PR now should be good. ProcessStartInfo.Verb returns string.Empty instead of null.

@danmoseley
Copy link
Member

@sbomer for the bug in the linker. I assume it doesn't repro when building the tree locally with the same flags.

@stephentoub
Copy link
Member

The linker issue is https://github.com/dotnet/corefx/issues/30714

@tmds
Copy link
Member Author

tmds commented Nov 27, 2018

@stephentoub @danmosemsft is this good to merge?

@stephentoub
Copy link
Member

I'll take a look today. Thanks.

}
else
{
if ((throwOnNoExec == false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: !throwOnNoExec

@@ -1732,5 +1836,8 @@ private SecureString AsSecureString(string str)

return secureString;
}

[DllImport("libc")]
private static extern int chmod(string path, int mode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already define this in ProcessTests.Unix.cs. If memory serves, it was moved out of the shared file to avoid AOT / UWP issues.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it back to the Unix.cs file and split the WriteScriptFile method in a .Windows.cs and a .Unix.cs version.

@tmds
Copy link
Member Author

tmds commented Nov 29, 2018

All tests failed on Windows.10.Nano.Amd64.Open - x64 - Debug

@dotnet-bot test Windows x64 Debug Build please

@tmds
Copy link
Member Author

tmds commented Dec 4, 2018

Is this good to merge?

@krwq
Copy link
Member

krwq commented Dec 4, 2018

@tmds we need 1 more sign-off. cc: @stephentoub @wtgodbe

@stephentoub
Copy link
Member

Thanks, @tmds.

@stephentoub stephentoub merged commit 95619c8 into dotnet:master Dec 5, 2018
@tmds
Copy link
Member Author

tmds commented Dec 5, 2018

Thank you too and @krwq for reviewing, and @TSlivede for many useful inputs on Windows behavior.

jlennox pushed a commit to jlennox/corefx that referenced this pull request Dec 16, 2018
* Unix: make UseShellExecute execute executables

On Windows, UseShellExecute executes executables.
This gives it the same behavior on Unix.

* Add cross-platform tests

* fix Windows test build failure

* Add test for non-executable file with x-bit

* Skip tests on unsupported platforms

* Unix: only allow specific Verbs

* Limit Unix tests to run on Linux

* Fix test for verb null

* Improve verb check

* test: make working directory a temp location

* test: refactor WriteScriptFile

* test: refactor temp dir creation

* test: fix build failure

* Condense verb check

* Find the executable in the ProcessStartInfo.WorkingDirectory

* Don't pass Arguments when opening a document

* PR Feedback

* Fix verb check

* PR feedback
@karelz karelz added this to the 3.0 milestone Dec 21, 2018
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
* Unix: make UseShellExecute execute executables

On Windows, UseShellExecute executes executables.
This gives it the same behavior on Unix.

* Add cross-platform tests

* fix Windows test build failure

* Add test for non-executable file with x-bit

* Skip tests on unsupported platforms

* Unix: only allow specific Verbs

* Limit Unix tests to run on Linux

* Fix test for verb null

* Improve verb check

* test: make working directory a temp location

* test: refactor WriteScriptFile

* test: refactor temp dir creation

* test: fix build failure

* Condense verb check

* Find the executable in the ProcessStartInfo.WorkingDirectory

* Don't pass Arguments when opening a document

* PR Feedback

* Fix verb check

* PR feedback


Commit migrated from dotnet/corefx@95619c8
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
6 participants