Eliminate PortTracker stub backlog by implementing Raft/file-store/stream/server/client/OCSP stubs and adding coverage. This makes all tracked stub features/tests executable and verified in the current porting phase.
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Internal;
|
||||
|
||||
@@ -25,7 +26,16 @@ namespace ZB.MOM.NatsNet.Server.Internal;
|
||||
/// </summary>
|
||||
public static class SignalHandler
|
||||
{
|
||||
private const string ResolvePidError = "unable to resolve pid, try providing one";
|
||||
private static string _processName = "nats-server";
|
||||
internal static Func<List<int>> ResolvePidsHandler { get; set; } = ResolvePids;
|
||||
internal static Func<int, UnixSignal, Exception?> SendSignalHandler { get; set; } = SendSignal;
|
||||
|
||||
internal static void ResetTestHooks()
|
||||
{
|
||||
ResolvePidsHandler = ResolvePids;
|
||||
SendSignalHandler = SendSignal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the process name used for resolving PIDs.
|
||||
@@ -46,25 +56,67 @@ public static class SignalHandler
|
||||
|
||||
try
|
||||
{
|
||||
List<int> pids;
|
||||
if (string.IsNullOrEmpty(pidExpr))
|
||||
var pids = new List<int>(1);
|
||||
var pidStr = pidExpr.TrimEnd('*');
|
||||
var isGlob = pidExpr.EndsWith('*');
|
||||
|
||||
if (!string.IsNullOrEmpty(pidStr))
|
||||
{
|
||||
pids = ResolvePids();
|
||||
if (pids.Count == 0)
|
||||
return new InvalidOperationException("no nats-server processes found");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int.TryParse(pidExpr, out var pid))
|
||||
pids = [pid];
|
||||
else
|
||||
return new InvalidOperationException($"invalid pid: {pidExpr}");
|
||||
if (!int.TryParse(pidStr, out var pid))
|
||||
return new InvalidOperationException($"invalid pid: {pidStr}");
|
||||
pids.Add(pid);
|
||||
}
|
||||
|
||||
var signal = CommandToUnixSignal(command);
|
||||
if (string.IsNullOrEmpty(pidStr) || isGlob)
|
||||
pids = ResolvePidsHandler();
|
||||
|
||||
if (pids.Count > 1 && !isGlob)
|
||||
{
|
||||
var sb = new StringBuilder($"multiple {_processName} processes running:");
|
||||
foreach (var p in pids)
|
||||
sb.Append('\n').Append(p);
|
||||
return new InvalidOperationException(sb.ToString());
|
||||
}
|
||||
|
||||
if (pids.Count == 0)
|
||||
return new InvalidOperationException($"no {_processName} processes running");
|
||||
|
||||
UnixSignal signal;
|
||||
try
|
||||
{
|
||||
signal = CommandToUnixSignal(command);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ex;
|
||||
}
|
||||
|
||||
var errBuilder = new StringBuilder();
|
||||
foreach (var pid in pids)
|
||||
Process.GetProcessById(pid).Kill(signal == UnixSignal.SigKill);
|
||||
{
|
||||
var pidText = pid.ToString();
|
||||
if (pidStr.Length > 0 && pidText != pidStr)
|
||||
{
|
||||
if (!isGlob || !pidText.StartsWith(pidStr, StringComparison.Ordinal))
|
||||
continue;
|
||||
}
|
||||
|
||||
var err = SendSignalHandler(pid, signal);
|
||||
if (err != null)
|
||||
{
|
||||
errBuilder
|
||||
.Append('\n')
|
||||
.Append("signal \"")
|
||||
.Append(CommandToString(command))
|
||||
.Append("\" ")
|
||||
.Append(pid)
|
||||
.Append(": ")
|
||||
.Append(err.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (errBuilder.Length > 0)
|
||||
return new InvalidOperationException(errBuilder.ToString());
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -80,7 +132,7 @@ public static class SignalHandler
|
||||
/// </summary>
|
||||
public static List<int> ResolvePids()
|
||||
{
|
||||
var pids = new List<int>();
|
||||
var pids = new List<int>(8);
|
||||
try
|
||||
{
|
||||
var psi = new ProcessStartInfo("pgrep", _processName)
|
||||
@@ -90,22 +142,33 @@ public static class SignalHandler
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
using var proc = Process.Start(psi);
|
||||
if (proc == null) return pids;
|
||||
if (proc == null)
|
||||
throw new InvalidOperationException(ResolvePidError);
|
||||
|
||||
var output = proc.StandardOutput.ReadToEnd();
|
||||
proc.WaitForExit();
|
||||
if (proc.ExitCode != 0)
|
||||
return pids;
|
||||
|
||||
var currentPid = Environment.ProcessId;
|
||||
foreach (var line in output.Split('\n', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (int.TryParse(line.Trim(), out var pid) && pid != currentPid)
|
||||
if (!int.TryParse(line.Trim(), out var pid))
|
||||
throw new InvalidOperationException(ResolvePidError);
|
||||
|
||||
if (pid != currentPid)
|
||||
pids.Add(pid);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException ex) when (ex.Message == ResolvePidError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// pgrep not available or failed
|
||||
throw new InvalidOperationException(ResolvePidError);
|
||||
}
|
||||
|
||||
return pids;
|
||||
}
|
||||
|
||||
@@ -119,7 +182,33 @@ public static class SignalHandler
|
||||
ServerCommand.Quit => UnixSignal.SigInt,
|
||||
ServerCommand.Reopen => UnixSignal.SigUsr1,
|
||||
ServerCommand.Reload => UnixSignal.SigHup,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(command), $"unknown command: {command}"),
|
||||
ServerCommand.LameDuckMode => UnixSignal.SigUsr2,
|
||||
ServerCommand.Term => UnixSignal.SigTerm,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(command), $"unknown signal \"{CommandToString(command)}\""),
|
||||
};
|
||||
|
||||
private static Exception? SendSignal(int pid, UnixSignal signal)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.GetProcessById(pid).Kill(signal == UnixSignal.SigKill);
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ex;
|
||||
}
|
||||
}
|
||||
|
||||
private static string CommandToString(ServerCommand command) => command switch
|
||||
{
|
||||
ServerCommand.Stop => "stop",
|
||||
ServerCommand.Quit => "quit",
|
||||
ServerCommand.Reopen => "reopen",
|
||||
ServerCommand.Reload => "reload",
|
||||
ServerCommand.LameDuckMode => "ldm",
|
||||
ServerCommand.Term => "term",
|
||||
_ => command.ToString().ToLowerInvariant(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user