mirror of
https://github.com/ZuneDev/MicrosoftIris.git
synced 2026-07-27 13:13:29 -07:00
Switch to NetMQ for inter-process debugging
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
using Microsoft.Iris.Animations;
|
using Microsoft.Iris.Animations;
|
||||||
using Microsoft.Iris.Data;
|
using Microsoft.Iris.Data;
|
||||||
|
using Microsoft.Iris.Debug;
|
||||||
using Microsoft.Iris.Input;
|
using Microsoft.Iris.Input;
|
||||||
using Microsoft.Iris.Library;
|
using Microsoft.Iris.Library;
|
||||||
using Microsoft.Iris.Markup;
|
using Microsoft.Iris.Markup;
|
||||||
@@ -135,7 +136,11 @@ namespace Microsoft.Iris
|
|||||||
get => DllResources.StaticDllResourcesOnly;
|
get => DllResources.StaticDllResourcesOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Debug.DebugSettings DebugSettings { get; } = new();
|
public static DebugSettings DebugSettings { get; } = new();
|
||||||
|
|
||||||
|
internal static IDebuggerServer Debugger { get; private set; }
|
||||||
|
|
||||||
|
public static event EventHandler DebuggerServerReady;
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
@@ -187,7 +192,12 @@ namespace Microsoft.Iris
|
|||||||
ErrorManager.OnErrors += new NotifyErrorBatch(NotifyErrorBatchHandler);
|
ErrorManager.OnErrors += new NotifyErrorBatch(NotifyErrorBatchHandler);
|
||||||
|
|
||||||
Debug.Trace.Initialize();
|
Debug.Trace.Initialize();
|
||||||
Debug.BridgeServer.Start(null);
|
|
||||||
|
if (DebugSettings.DebugConnectionUri != null)
|
||||||
|
{
|
||||||
|
Debugger = new ZmqDebuggerServer(DebugSettings.DebugConnectionUri);
|
||||||
|
DebuggerServerReady?.Invoke(Debugger, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
MarkupSystem.Startup(!fullInitialization);
|
MarkupSystem.Startup(!fullInitialization);
|
||||||
StaticServices.Initialize();
|
StaticServices.Initialize();
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
using CoreRemoting;
|
|
||||||
using CoreRemoting.DependencyInjection;
|
|
||||||
using CoreRemoting.Serialization.Binary;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.Iris.Debug;
|
|
||||||
|
|
||||||
internal class BridgeServer : IBridge, IDisposable
|
|
||||||
{
|
|
||||||
private static RemotingServer _server;
|
|
||||||
|
|
||||||
public static IBridge Current { get; private set; }
|
|
||||||
|
|
||||||
public event EventHandler<Data.InterpreterEntry> InterpreterStep;
|
|
||||||
public event Action<string> DispatcherStep;
|
|
||||||
|
|
||||||
public static void Start(ServerConfig config)
|
|
||||||
{
|
|
||||||
_server = new RemotingServer(new ServerConfig
|
|
||||||
{
|
|
||||||
HostName = "localhost",
|
|
||||||
NetworkPort = 9090,
|
|
||||||
MessageEncryption = false,
|
|
||||||
Serializer = new BinarySerializerAdapter(),
|
|
||||||
RegisterServicesAction = container =>
|
|
||||||
{
|
|
||||||
container.RegisterService<IBridge, BridgeServer>(ServiceLifetime.Singleton);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Current = _server.ServiceRegistry.GetService<IBridge>();
|
|
||||||
|
|
||||||
_server.Error += OnServerError;
|
|
||||||
_server.BeforeCall += (_, ctx) =>
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
_server.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void OnServerError(object sender, Exception e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry)
|
|
||||||
{
|
|
||||||
InterpreterStep?.Invoke(context, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LogDispatcher(string message)
|
|
||||||
{
|
|
||||||
DispatcherStep?.Invoke(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() => _server.Dispose();
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using CoreRemoting;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
|
||||||
#if NET40_OR_GREATER || NET6_0_OR_GREATER
|
#if NET40_OR_GREATER || NET6_0_OR_GREATER
|
||||||
@@ -23,7 +22,7 @@ namespace Microsoft.Iris.Debug
|
|||||||
|
|
||||||
public List<string> Breakpoints { get; } = new List<string>();
|
public List<string> Breakpoints { get; } = new List<string>();
|
||||||
|
|
||||||
public ServerConfig DebugServerConfig { get; set; }
|
public string DebugConnectionUri { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DecompilationResult
|
public class DecompilationResult
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Microsoft.Iris.Debug;
|
||||||
|
|
||||||
|
public enum DebuggerMessageType : int
|
||||||
|
{
|
||||||
|
Null = 0,
|
||||||
|
|
||||||
|
InterpreterOpCode,
|
||||||
|
DispatcherStep,
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.Iris.Debug;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The contract between the UIX runtime and debuggers.
|
|
||||||
/// </summary>
|
|
||||||
public interface IBridge
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when the UIX interpreter steps forward.
|
|
||||||
/// </summary>
|
|
||||||
event EventHandler<Data.InterpreterEntry> InterpreterStep;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fired when the UIX dispatcher executes another call from the queue.
|
|
||||||
/// </summary>
|
|
||||||
event Action<string> DispatcherStep;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Logs the context, opcode, and arguments of an instruction
|
|
||||||
/// executed by <c>Microsoft.Iris.Markup.Interpreter</c>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
/// <param name="entry"></param>
|
|
||||||
public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Logs the string representation of a dispatcher step.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
public void LogDispatcher(string message);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.Iris.Debug.Data;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.Iris.Debug;
|
||||||
|
|
||||||
|
public interface IDebuggerClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when the UIX interpreter steps forward.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler<InterpreterEntry> InterpreterStep;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when the UIX dispatcher executes another call from the queue.
|
||||||
|
/// </summary>
|
||||||
|
event Action<string> DispatcherStep;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.Iris.Debug.Data;
|
||||||
|
|
||||||
|
namespace Microsoft.Iris.Debug;
|
||||||
|
|
||||||
|
internal interface IDebuggerServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logs the context, opcode, and arguments of an instruction
|
||||||
|
/// executed by <c>Microsoft.Iris.Markup.Interpreter</c>.
|
||||||
|
/// </summary>
|
||||||
|
public void LogInterpreterOpCode(object context, InterpreterEntry entry);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs the string representation of a dispatcher step.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
public void LogDispatcher(string message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using Microsoft.Iris.Debug.Data;
|
||||||
|
using NetMQ;
|
||||||
|
using NetMQ.Sockets;
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.Iris.Debug;
|
||||||
|
|
||||||
|
public class ZmqDebuggerClient : IDebuggerClient, IDisposable
|
||||||
|
{
|
||||||
|
private readonly SubscriberSocket _subSocket;
|
||||||
|
|
||||||
|
public event EventHandler<InterpreterEntry> InterpreterStep;
|
||||||
|
public event Action<string> DispatcherStep;
|
||||||
|
|
||||||
|
public ZmqDebuggerClient(string connectionUri)
|
||||||
|
{
|
||||||
|
_subSocket = new();
|
||||||
|
_subSocket.Connect(connectionUri);
|
||||||
|
_subSocket.SubscribeToAnyTopic();
|
||||||
|
|
||||||
|
System.Threading.Thread th = new(MessageRecieveLoop);
|
||||||
|
th.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => _subSocket.Dispose();
|
||||||
|
|
||||||
|
private void MessageRecieveLoop()
|
||||||
|
{
|
||||||
|
while (!_subSocket.IsDisposed)
|
||||||
|
{
|
||||||
|
var type = RecieveDebuggerMessage(_subSocket, out var bytes);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DebuggerMessageType.InterpreterOpCode:
|
||||||
|
string entry = Encoding.Unicode.GetString(bytes);
|
||||||
|
InterpreterStep?.Invoke(this, null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DebuggerMessageType.DispatcherStep:
|
||||||
|
string message = Encoding.Unicode.GetString(bytes);
|
||||||
|
DispatcherStep?.Invoke(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DebuggerMessageType RecieveDebuggerMessage(SubscriberSocket socket, out byte[] bytes)
|
||||||
|
{
|
||||||
|
var frames = socket.ReceiveMultipartBytes(2);
|
||||||
|
|
||||||
|
bytes = frames[1];
|
||||||
|
return (DebuggerMessageType)BitConverter.ToInt32(frames[0], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using NetMQ;
|
||||||
|
using NetMQ.Sockets;
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.Iris.Debug;
|
||||||
|
|
||||||
|
internal class ZmqDebuggerServer : IDebuggerServer, IDisposable
|
||||||
|
{
|
||||||
|
public static IDebuggerServer Current { get; private set; }
|
||||||
|
|
||||||
|
private readonly PublisherSocket _pubSocket;
|
||||||
|
private readonly byte[][] _messageFrame = new byte[2][];
|
||||||
|
|
||||||
|
public ZmqDebuggerServer(string connectionUri)
|
||||||
|
{
|
||||||
|
_pubSocket = new();
|
||||||
|
_pubSocket.Bind(connectionUri);
|
||||||
|
|
||||||
|
Current = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry)
|
||||||
|
{
|
||||||
|
SendDebuggerMessage(DebuggerMessageType.InterpreterOpCode, entry.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogDispatcher(string message)
|
||||||
|
{
|
||||||
|
SendDebuggerMessage(DebuggerMessageType.DispatcherStep, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => _pubSocket.Dispose();
|
||||||
|
|
||||||
|
private void SendDebuggerMessage(DebuggerMessageType type, string message, Encoding encoding = null)
|
||||||
|
{
|
||||||
|
var messageBytes = (encoding ?? Encoding.Unicode).GetBytes(message);
|
||||||
|
SendDebuggerMessage(type, messageBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendDebuggerMessage(DebuggerMessageType type, byte[] bytes)
|
||||||
|
{
|
||||||
|
_messageFrame[0] = BitConverter.GetBytes((int)type);
|
||||||
|
_messageFrame[1] = bytes;
|
||||||
|
|
||||||
|
_pubSocket.SendMultipartBytes(_messageFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,7 +66,7 @@ namespace Microsoft.Iris.Markup
|
|||||||
bool errorsDetected = false;
|
bool errorsDetected = false;
|
||||||
object result = null;
|
object result = null;
|
||||||
bool wasInDebugState = false;
|
bool wasInDebugState = false;
|
||||||
bool debugging = BridgeServer.Current != null;
|
bool debugging = Application.Debugger != null;
|
||||||
|
|
||||||
while (!errorsDetected)
|
while (!errorsDetected)
|
||||||
{
|
{
|
||||||
@@ -670,7 +670,7 @@ namespace Microsoft.Iris.Markup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BridgeServer.Current?.LogInterpreterOpCode(opCode, entry);
|
Application.Debugger?.LogInterpreterOpCode(opCode, entry);
|
||||||
}
|
}
|
||||||
while (stack.Count > count)
|
while (stack.Count > count)
|
||||||
{
|
{
|
||||||
@@ -1630,7 +1630,7 @@ namespace Microsoft.Iris.Markup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BridgeServer.Current?.LogInterpreterOpCode(opCode, entry);
|
Application.Debugger?.LogInterpreterOpCode(opCode, entry);
|
||||||
|
|
||||||
if (stack.Count != xmlStack.Count)
|
if (stack.Count != xmlStack.Count)
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace Microsoft.Iris.Queues
|
|||||||
QueueItem nextItem = queue.GetNextItem();
|
QueueItem nextItem = queue.GetNextItem();
|
||||||
if (nextItem != null)
|
if (nextItem != null)
|
||||||
{
|
{
|
||||||
BridgeServer.Current.LogDispatcher(nextItem.ToDebugPacketString());
|
Application.Debugger.LogDispatcher(nextItem.ToDebugPacketString());
|
||||||
nextItem.Dispatch();
|
nextItem.Dispatch();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\UIX.RenderApi\UIX.RenderApi.csproj" />
|
<ProjectReference Include="..\UIX.RenderApi\UIX.RenderApi.csproj" />
|
||||||
<PackageReference Include="CoreRemoting" Version="1.1.14" />
|
<PackageReference Include="NetMQ" Version="4.0.1.12" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) ">
|
<ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) ">
|
||||||
|
|||||||
Reference in New Issue
Block a user