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.Data;
|
||||
using Microsoft.Iris.Debug;
|
||||
using Microsoft.Iris.Input;
|
||||
using Microsoft.Iris.Library;
|
||||
using Microsoft.Iris.Markup;
|
||||
@@ -135,7 +136,11 @@ namespace Microsoft.Iris
|
||||
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()
|
||||
{
|
||||
@@ -187,7 +192,12 @@ namespace Microsoft.Iris
|
||||
ErrorManager.OnErrors += new NotifyErrorBatch(NotifyErrorBatchHandler);
|
||||
|
||||
Debug.Trace.Initialize();
|
||||
Debug.BridgeServer.Start(null);
|
||||
|
||||
if (DebugSettings.DebugConnectionUri != null)
|
||||
{
|
||||
Debugger = new ZmqDebuggerServer(DebugSettings.DebugConnectionUri);
|
||||
DebuggerServerReady?.Invoke(Debugger, EventArgs.Empty);
|
||||
}
|
||||
|
||||
MarkupSystem.Startup(!fullInitialization);
|
||||
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;
|
||||
|
||||
#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 ServerConfig DebugServerConfig { get; set; }
|
||||
public string DebugConnectionUri { get; set; }
|
||||
}
|
||||
|
||||
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;
|
||||
object result = null;
|
||||
bool wasInDebugState = false;
|
||||
bool debugging = BridgeServer.Current != null;
|
||||
bool debugging = Application.Debugger != null;
|
||||
|
||||
while (!errorsDetected)
|
||||
{
|
||||
@@ -670,7 +670,7 @@ namespace Microsoft.Iris.Markup
|
||||
}
|
||||
}
|
||||
|
||||
BridgeServer.Current?.LogInterpreterOpCode(opCode, entry);
|
||||
Application.Debugger?.LogInterpreterOpCode(opCode, entry);
|
||||
}
|
||||
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)
|
||||
throw new InvalidOperationException(
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Microsoft.Iris.Queues
|
||||
QueueItem nextItem = queue.GetNextItem();
|
||||
if (nextItem != null)
|
||||
{
|
||||
BridgeServer.Current.LogDispatcher(nextItem.ToDebugPacketString());
|
||||
Application.Debugger.LogDispatcher(nextItem.ToDebugPacketString());
|
||||
nextItem.Dispatch();
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user