Skip to content

Instantly share code, notes, and snippets.

@TheBuzzSaw
Last active January 28, 2019 22:10
Show Gist options
  • Save TheBuzzSaw/69c16a9dad2b27857b0070008ac9fb0d to your computer and use it in GitHub Desktop.
Save TheBuzzSaw/69c16a9dad2b27857b0070008ac9fb0d to your computer and use it in GitHub Desktop.
Demonstration of Pipe Bug
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
</Project>
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PipeBugDemo
{
class Program
{
const string OutputFile = "debug.txt";
static async Task Main(string[] args)
{
try
{
if (args.Length > 0)
await RunClientAsync(args[0]);
else
await RunServerAsync();
}
catch (Exception ex)
{
for (var e = ex; e != null; e = e.InnerException)
{
Console.WriteLine("--- --- ---");
Console.WriteLine(e.GetType());
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
static async Task RunClientAsync(string clientHandle)
{
await File.WriteAllTextAsync(
OutputFile,
"Begin " + DateTime.Now.ToString("s") + Environment.NewLine);
using (var stream = new AnonymousPipeClientStream(PipeDirection.In, clientHandle))
{
var buffer = new byte[256];
while (true)
{
int n = await stream.ReadAsync(buffer, 0, buffer.Length);
if (n < 1)
break;
var message = Encoding.UTF8.GetString(buffer, 0, n);
await File.AppendAllTextAsync(
OutputFile,
message + Environment.NewLine);
}
}
await File.AppendAllTextAsync(
OutputFile,
"End " + DateTime.Now.ToString("s") + Environment.NewLine);
}
static async Task RunServerAsync()
{
var process = new Process();
using (var stream = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
{
var startInfo = new ProcessStartInfo
{
FileName = Environment.CommandLine,
CreateNoWindow = true,
UseShellExecute = false
};
if (startInfo.FileName.EndsWith(".dll"))
{
startInfo.ArgumentList.Add(startInfo.FileName);
startInfo.FileName = GetDotNet();
}
startInfo.ArgumentList.Add(stream.GetClientHandleAsString());
process.StartInfo = startInfo;
Console.WriteLine("Starting client...");
process.Start();
stream.DisposeLocalCopyOfClientHandle();
for (int i = 0; i < 4; ++i)
{
string message = "Hello " + Guid.NewGuid();
Console.WriteLine("Sending message: " + message);
var buffer = Encoding.UTF8.GetBytes(message);
await stream.WriteAsync(buffer, 0, buffer.Length);
await Task.Delay(400);
}
}
Console.WriteLine("Closed stream. Waiting for child process to exit...");
if (!process.WaitForExit(2000))
{
// If you reach this point, the test failed.
// Disposing the server stream was supposed to cause the client ReadAsync to return zero.
Console.WriteLine("Killing process :(");
process.Kill();
}
Console.WriteLine("Done.");
}
static string GetDotNet()
{
// Yes. Hacky. Go away.
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return @"C:\Program Files\dotnet\dotnet.exe";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return "/usr/local/share/dotnet/dotnet";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return "/usr/bin/dotnet";
throw new PlatformNotSupportedException("What OS are you running, dawg?");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment