-
-
Notifications
You must be signed in to change notification settings - Fork 144
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Piped Mode: Flush data stream before closing StdIn
- Loading branch information
Showing
6 changed files
with
99 additions
and
95 deletions.
There are no files selected for viewing
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
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
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,85 @@ | ||
using System; | ||
using System.IO; | ||
using System.IO.Pipes; | ||
using System.Runtime.Serialization.Formatters.Binary; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace gsudo.Rpc | ||
{ | ||
class Connection : IDisposable | ||
{ | ||
private PipeStream _dataStream; | ||
private PipeStream _controlStream; | ||
|
||
public Connection(PipeStream ControlStream, PipeStream DataStream) | ||
{ | ||
_dataStream = DataStream; | ||
_controlStream = ControlStream; | ||
} | ||
|
||
public Stream DataStream => _dataStream; | ||
public Stream ControlStream => _controlStream; | ||
|
||
private ManualResetEvent DisconnectedResetEvent { get; } = new ManualResetEvent(false); | ||
public WaitHandle DisconnectedWaitHandle => DisconnectedResetEvent; | ||
|
||
public bool IsAlive { get; private set; } = true; | ||
public void SignalDisconnected() | ||
{ | ||
IsAlive = false; | ||
DisconnectedResetEvent.Set(); | ||
} | ||
|
||
public async Task FlushAndCloseAll() | ||
{ | ||
IsAlive = false; | ||
await FlushDataStream().ConfigureAwait(false); | ||
await FlushControlStream().ConfigureAwait(false); | ||
DataStream.Close(); | ||
ControlStream.Close(); | ||
} | ||
|
||
public Task FlushDataStream() => Flush(_dataStream); | ||
public Task FlushControlStream() => Flush(_controlStream); | ||
|
||
private async Task Flush(PipeStream npStream) | ||
{ | ||
try | ||
{ | ||
await Task.Delay(1).ConfigureAwait(false); | ||
await npStream.FlushAsync().ConfigureAwait(false); | ||
npStream.WaitForPipeDrain(); | ||
await Task.Delay(1).ConfigureAwait(false); | ||
} | ||
catch (ObjectDisposedException) { } | ||
catch (Exception) { } | ||
} | ||
|
||
public async Task WriteElevationRequest(ElevationRequest elevationRequest) | ||
{ | ||
// Using Binary instead of Newtonsoft.JSON to reduce load times. | ||
var ms = new System.IO.MemoryStream(); | ||
new BinaryFormatter() | ||
{ TypeFormat = System.Runtime.Serialization.Formatters.FormatterTypeStyle.TypesAlways, Binder = new MySerializationBinder() } | ||
.Serialize(ms, elevationRequest); | ||
ms.Seek(0, System.IO.SeekOrigin.Begin); | ||
|
||
byte[] lengthArray = BitConverter.GetBytes(ms.Length); | ||
Logger.Instance.Log($"ElevationRequest length {ms.Length}", LogLevel.Debug); | ||
|
||
await ControlStream.WriteAsync(lengthArray, 0, sizeof(int)).ConfigureAwait(false); | ||
await ControlStream.WriteAsync(ms.ToArray(), 0, (int)ms.Length).ConfigureAwait(false); | ||
await ControlStream.FlushAsync().ConfigureAwait(false); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
DataStream?.Close(); | ||
DataStream?.Dispose(); | ||
ControlStream?.Close(); | ||
ControlStream?.Dispose(); | ||
IsAlive = false; | ||
} | ||
} | ||
} |
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 |
---|---|---|
@@ -1,83 +1,9 @@ | ||
using System; | ||
using System.IO; | ||
using System.IO.Pipes; | ||
using System.Runtime.Serialization.Formatters.Binary; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Threading.Tasks; | ||
|
||
namespace gsudo.Rpc | ||
{ | ||
internal interface IRpcClient | ||
{ | ||
Task<Connection> Connect(int? clientPid, bool failFast); | ||
} | ||
|
||
class Connection : IDisposable | ||
{ | ||
public Stream DataStream { get; set; } | ||
public Stream ControlStream { get; set; } | ||
|
||
private ManualResetEvent DisconnectedResetEvent { get; } = new ManualResetEvent(false); | ||
public WaitHandle DisconnectedWaitHandle => DisconnectedResetEvent; | ||
|
||
public bool IsAlive { get; private set; } = true; | ||
public void SignalDisconnected() | ||
{ | ||
IsAlive = false; | ||
DisconnectedResetEvent.Set(); | ||
} | ||
|
||
public async Task FlushAndCloseAll() | ||
{ | ||
IsAlive = false; | ||
await Flush(DataStream).ConfigureAwait(false); | ||
await Flush(ControlStream).ConfigureAwait(false); | ||
DataStream.Close(); | ||
ControlStream.Close(); | ||
} | ||
|
||
private static async Task Flush(Stream DataStream) | ||
{ | ||
if (DataStream is NamedPipeServerStream) | ||
{ | ||
var npStream = DataStream as NamedPipeServerStream; | ||
try | ||
{ | ||
await Task.Delay(1).ConfigureAwait(false); | ||
await npStream.FlushAsync().ConfigureAwait(false); | ||
npStream.WaitForPipeDrain(); | ||
await Task.Delay(1).ConfigureAwait(false); | ||
} | ||
catch (Exception) { } | ||
} | ||
else | ||
DataStream.Close(); | ||
} | ||
|
||
public async Task WriteElevationRequest(ElevationRequest elevationRequest) | ||
{ | ||
// Using Binary instead of Newtonsoft.JSON to reduce load times. | ||
var ms = new System.IO.MemoryStream(); | ||
new BinaryFormatter() | ||
{ TypeFormat = System.Runtime.Serialization.Formatters.FormatterTypeStyle.TypesAlways, Binder = new MySerializationBinder() } | ||
.Serialize(ms, elevationRequest); | ||
ms.Seek(0, System.IO.SeekOrigin.Begin); | ||
|
||
byte[] lengthArray = BitConverter.GetBytes(ms.Length); | ||
Logger.Instance.Log($"ElevationRequest length {ms.Length}", LogLevel.Debug); | ||
|
||
await ControlStream.WriteAsync(lengthArray, 0, sizeof(int)).ConfigureAwait(false); | ||
await ControlStream.WriteAsync(ms.ToArray(), 0, (int)ms.Length).ConfigureAwait(false); | ||
await ControlStream.FlushAsync().ConfigureAwait(false); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
DataStream?.Close(); | ||
DataStream?.Dispose(); | ||
ControlStream?.Close(); | ||
ControlStream?.Dispose(); | ||
IsAlive = false; | ||
} | ||
} | ||
} |
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
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