Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash on pipe timeout #529

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions MacroDeck/MacroDeck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
using SuchByte.MacroDeck.Language;
using SuchByte.MacroDeck.Logging;
using SuchByte.MacroDeck.Notifications;
using SuchByte.MacroDeck.Pipes;
using SuchByte.MacroDeck.Pipe;
using SuchByte.MacroDeck.Plugins;
using SuchByte.MacroDeck.Profiles;
using SuchByte.MacroDeck.Properties;
Expand Down Expand Up @@ -266,23 +266,22 @@ public static void RestartMacroDeck(string parameters = "")

public static void ShowMainWindow()
{
if (SyncContext == null)
if (SyncContext is null)
{
CreateMainForm();
} else
return;
}

SyncContext.Send(_ =>
{
SyncContext.Send(o =>
{
CreateMainForm();
}, null);
}
CreateMainForm();
}, null);
}

private static void CreateMainForm()
{
if (Application.OpenForms.OfType<MainWindow>().Any()
&& _mainWindow.IsDisposed == false
&& _mainWindow.IsHandleCreated)
&& _mainWindow is { IsDisposed: false, IsHandleCreated: true })
{
if (_mainWindow.InvokeRequired)
{
Expand Down
32 changes: 18 additions & 14 deletions MacroDeck/Pipe/MacroDeckPipeClient.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
using System.IO.Pipes;

namespace SuchByte.MacroDeck.Pipes;
namespace SuchByte.MacroDeck.Pipe;

public class MacroDeckPipeClient
public static class MacroDeckPipeClient
{

internal static bool SendShowMainWindowMessage()
internal static Task<bool> SendShowMainWindowMessage()
{
return SendPipeMessage("show");
}


internal static bool SendPipeMessage(string message)
private static async Task<bool> SendPipeMessage(string message)
{
var client = new NamedPipeClientStream("macrodeck");
client.Connect(2000);
if (client.IsConnected)
try
{
var buffer = Encoding.ASCII.GetBytes(message);
client.Write(buffer, 0, buffer.Length);
client.Close();
client.Dispose();
return true;
await using var client = new NamedPipeClientStream("macrodeck");
await client.ConnectAsync(2000);
if (client.IsConnected)
{
var bytes = Encoding.ASCII.GetBytes(message);
client.Write(bytes, 0, bytes.Length);
return true;
}
}

catch (TimeoutException)
{
// Ignore
}

return false;
}

Expand Down
70 changes: 30 additions & 40 deletions MacroDeck/Pipe/MacroDeckPipeServer.cs
Original file line number Diff line number Diff line change
@@ -1,53 +1,43 @@
using System.IO.Pipes;
using System.Threading;
using System.IO;
using System.IO.Pipes;
using SuchByte.MacroDeck.Logging;

namespace SuchByte.MacroDeck.Pipes;
namespace SuchByte.MacroDeck.Pipe;

public delegate void DelegateMessage(string message);
public class MacroDeckPipeServer
{
public static event DelegateMessage PipeMessage;
public static event Action<string>? PipeMessage;


private static void WaitForConnectionCallBack(IAsyncResult iar)
public static void Initialize()
{
try
{
using var pipeServer = (NamedPipeServerStream)iar.AsyncState;
pipeServer.EndWaitForConnection(iar);
var buffer = new byte[255];
pipeServer.Read(buffer, 0, 255);
var stringData = Encoding.ASCII.GetString(buffer).Trim('\0');
var t = new Thread(() => PipeMessage.Invoke(stringData));
t.SetApartmentState(ApartmentState.STA);
t.Start();
pipeServer.Close();
SpawnServerStream();
}
catch
{
}
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server");
Task.Run(async () => await HandleConnections().ConfigureAwait(false));
}

private static void SpawnServerStream()
private static async Task HandleConnections()
{
try
{
MacroDeckLogger.Trace(typeof(MacroDeckPipeServer), "Spawning new server stream...");
var pipeServer = new NamedPipeServerStream("macrodeck", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, pipeServer);
}
catch (Exception ex)
do
{
MacroDeckLogger.Error(typeof(MacroDeckPipeServer), $"Failed: {ex.Message}");
}
}

public static void Initialize()
{
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server");
SpawnServerStream();
MacroDeckLogger.Info(typeof(MacroDeckPipeServer), "Initializing pipe server complete");
await using var pipeServer = new NamedPipeServerStream("macrodeck", PipeDirection.InOut, 1);
using var sr = new StreamReader(pipeServer);
try
{
await pipeServer.WaitForConnectionAsync();
pipeServer.WaitForPipeDrain();
var result = await sr.ReadLineAsync();
PipeMessage?.Invoke(result);
}
catch (Exception ex)
{
MacroDeckLogger.Error(typeof(MacroDeckPipeServer), $"Failed: {ex.Message}");
}
finally
{
if (pipeServer.IsConnected)
{
pipeServer.Disconnect();
}
}
} while (true);
}
}
23 changes: 13 additions & 10 deletions MacroDeck/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using SuchByte.MacroDeck.Logging;
using SuchByte.MacroDeck.Pipes;
using SuchByte.MacroDeck.Startup;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using SuchByte.MacroDeck.Server;
using SuchByte.MacroDeck.Pipe;

namespace SuchByte.MacroDeck;

Expand All @@ -25,26 +22,32 @@ private static void Main(string[] args)


var startParameters = StartParameters.ParseParameters(args);
CheckRunningInstance(startParameters.IgnorePidCheck);
CheckRunningInstance(startParameters.IgnorePidCheck).Wait();

ApplicationPaths.Initialize(startParameters.PortableMode);

MacroDeck.Start(startParameters);
}

private static void CheckRunningInstance(int ignoredPid)
private static async Task CheckRunningInstance(int ignoredPid)
{
var proc = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(proc.ProcessName).Where(x => ignoredPid == 0 || x.Id != ignoredPid).ToArray();
if (processes?.Length <= 1) return;
if (MacroDeckPipeClient.SendShowMainWindowMessage())
var processes = Process.GetProcessesByName(proc.ProcessName)
.Where(x => ignoredPid == 0 || x.Id != ignoredPid)
.ToArray();
if (processes.Length <= 1)
{
return;
}

if (await MacroDeckPipeClient.SendShowMainWindowMessage())
{
Environment.Exit(0);
return;
}

// Kill instance if no response
foreach (var p in processes?.Where(x => x.Id != proc.Id) ?? Array.Empty<Process>())
foreach (var p in processes.Where(x => x.Id != proc.Id))
{
try
{
Expand Down
Loading