forked from MessagePack-CSharp/MessagePack-CSharp
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
avoiding problem which empty proxy class is created in linux and mac(M…
…essagePack-CSharp#355) It is because dotnet SDK's msbuild in linux and mac cannot resolve `net4x` targetframework. This fix changes to following behavior in generating project info. 1. execute `dotnet msbuild` with output msbuild's binary log 2. if failed, execute `msbuild` with output msbuild's binary log 3. if success with `dotnet msbuild` or `msbuild`, analyze binary log
- Loading branch information
Showing
2 changed files
with
236 additions
and
25 deletions.
There are no files selected for viewing
130 changes: 130 additions & 0 deletions
130
src/MessagePack.UniversalCodeGenerator/Utils/ProcessUtil.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
using System.Diagnostics; | ||
using System; | ||
using System.IO; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace MessagePack.CodeGenerator | ||
{ | ||
internal static class ProcessUtil | ||
{ | ||
public static async Task<int> ExecuteProcessAsync(string fileName, string args, Stream stdout, Stream stderr, TextReader stdin, CancellationToken ct = default(CancellationToken)) | ||
{ | ||
var psi = new ProcessStartInfo(fileName, args); | ||
psi.UseShellExecute = false; | ||
psi.CreateNoWindow = true; | ||
psi.RedirectStandardError = stderr != null; | ||
psi.RedirectStandardOutput = stdout != null; | ||
psi.RedirectStandardInput = stdin != null; | ||
using (var proc = new Process()) | ||
using (var cts = new CancellationTokenSource()) | ||
using (var exitedct = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, ct)) | ||
{ | ||
proc.StartInfo = psi; | ||
proc.EnableRaisingEvents = true; | ||
proc.Exited += (sender, ev) => | ||
{ | ||
cts.Cancel(); | ||
}; | ||
if (!proc.Start()) | ||
{ | ||
throw new InvalidOperationException($"failed to start process(fileName = {fileName}, args = {args})"); | ||
} | ||
int exitCode = 0; | ||
await Task.WhenAll( | ||
Task.Run(() => | ||
{ | ||
exitCode = StdinTask(proc, stdin, exitedct, cts); | ||
if(exitCode < 0) | ||
{ | ||
proc.Dispose(); | ||
} | ||
}) | ||
, | ||
Task.Run(async () => | ||
{ | ||
if (stdout != null) | ||
{ | ||
await RedirectOutputTask(proc.StandardOutput.BaseStream, stdout, exitedct.Token, "stdout"); | ||
} | ||
}) | ||
, | ||
Task.Run(async () => | ||
{ | ||
if (stderr != null) | ||
{ | ||
await RedirectOutputTask(proc.StandardError.BaseStream, stderr, exitedct.Token, "stderr"); | ||
} | ||
}) | ||
); | ||
if(exitCode >= 0) | ||
{ | ||
return proc.ExitCode; | ||
} | ||
else | ||
{ | ||
return -1; | ||
} | ||
} | ||
} | ||
static int StdinTask(Process proc, TextReader stdin, CancellationTokenSource exitedct, CancellationTokenSource cts) | ||
{ | ||
if (stdin != null) | ||
{ | ||
while (!exitedct.Token.IsCancellationRequested) | ||
{ | ||
var l = stdin.ReadLine(); | ||
if (l == null) | ||
{ | ||
break; | ||
} | ||
proc.StandardInput.WriteLine(l); | ||
} | ||
proc.StandardInput.Dispose(); | ||
} | ||
exitedct.Token.WaitHandle.WaitOne(); | ||
if (cts.IsCancellationRequested) | ||
{ | ||
proc.WaitForExit(); | ||
var exitCode = proc.ExitCode; | ||
return exitCode; | ||
} | ||
else | ||
{ | ||
proc.StandardOutput.Dispose(); | ||
proc.StandardError.Dispose(); | ||
proc.Kill(); | ||
return -1; | ||
} | ||
} | ||
|
||
static async Task RedirectOutputTask(Stream procStdout, Stream stdout, CancellationToken ct, string suffix) | ||
{ | ||
if (stdout != null) | ||
{ | ||
var buf = new byte[1024]; | ||
while (!ct.IsCancellationRequested) | ||
{ | ||
try | ||
{ | ||
var bytesread = await procStdout.ReadAsync(buf, 0, 1024, ct).ConfigureAwait(false); | ||
if(bytesread <= 0) | ||
{ | ||
break; | ||
} | ||
stdout.Write(buf, 0, bytesread); | ||
} | ||
catch(NullReferenceException) | ||
{ | ||
break; | ||
} | ||
catch(ObjectDisposedException) | ||
{ | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters