Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mdaneri committed Nov 19, 2024
1 parent 0e5765d commit d959b34
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 132 deletions.
40 changes: 40 additions & 0 deletions src/PodeMonitor/PipeNameGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.IO;
namespace PodeMonitor
{
public static class PipeNameGenerator
{
private const string WindowsPipePrefix = @"\\.\pipe\"; // Windows pipe namespace
private const int MaxUnixPathLength = 104; // Max length for Unix domain sockets on macOS
private const string UnixTempDir = "/tmp"; // Short temporary directory for Unix systems

public static string GeneratePipeName()
{
// Generate a unique name based on a GUID
string uniqueId = Guid.NewGuid().ToString("N").Substring(0, 8);

if (OperatingSystem.IsWindows())
{
// Use Windows named pipe format
return $"{WindowsPipePrefix}PodePipe_{uniqueId}";
}
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
// Use Unix domain socket format with a shorter temp directory
string pipePath = Path.Combine(UnixTempDir, $"PodePipe_{uniqueId}");

// Ensure the path is within the allowed length for Unix domain sockets
if (pipePath.Length > MaxUnixPathLength)
{
throw new InvalidOperationException($"Generated pipe path exceeds the maximum length of {MaxUnixPathLength} characters: {pipePath}");
}

return pipePath;
}
else
{
throw new PlatformNotSupportedException("Unsupported operating system for pipe name generation.");
}
}
}
}
2 changes: 1 addition & 1 deletion src/PodeMonitor/PodeMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public PodeMonitor(PodeMonitorWorkerOptions options)
StartRetryDelayMs = options.StartRetryDelayMs;

// Generate a unique pipe name for communication
_pipeName = $"PodePipe_{Guid.NewGuid()}";
_pipeName = PipeNameGenerator.GeneratePipeName();
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, $"Initialized PodeMonitor with pipe name: {_pipeName}");
}

Expand Down
125 changes: 42 additions & 83 deletions src/PodeMonitor/PodeMonitorMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ namespace PodeMonitor
/// </summary>
public static partial class Program
{
// Platform-dependent signal registration (for Linux/macOS)
[LibraryImport("libc", EntryPoint = "signal")]
private static partial int Signal(int signum, Action<int> handler);
// Platform-dependent signal registration (for linux/macOS)
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SignalHandler(int signum);

[LibraryImport("libc", EntryPoint = "signal")]
private static partial int Signal(int signum, SignalHandler handler);

private const int SIGSTOP = 19; // Signal for pause
private const int SIGTSTP = 20; // Signal for pause
private const int SIGCONT = 18; // Signal for continue
private const int SIGHUP = 1; // Signal for restart
private const int SIGTERM = 15; // Signal for gracefully terminate a process.

private static PodeMonitorWorker _workerInstance; // Global instance for managing worker operations

/// <summary>
Expand Down Expand Up @@ -115,16 +119,17 @@ private static IHostBuilder CreateHostBuilder(string[] args, string customConfig

#if ENABLE_LIFECYCLE_OPERATIONS
/// <summary>
/// Configures the Pode service for Linux, including signal handling.
/// Configures the Pode service for linux, including signal handling.
/// </summary>
/// <param name="builder">The host builder.</param>
[SupportedOSPlatform("Linux")]
[SupportedOSPlatform("linux")]
private static void ConfigureLinux(IHostBuilder builder)
{
// Handle Linux signals for pause, resume, and restart
_ = Signal(SIGSTOP, _ => HandlePause());
_ = Signal(SIGCONT, _ => HandleContinue());
_ = Signal(SIGHUP, _ => HandleRestart());
// Handle linux signals for pause, resume, and restart
Signal(SIGTSTP, HandleSignalStop);
Signal(SIGCONT, HandleSignalContinue);
Signal(SIGHUP, HandleSignalRestart);


builder.UseSystemd();
builder.Build().Run();
Expand All @@ -138,10 +143,10 @@ private static void ConfigureLinux(IHostBuilder builder)
private static void ConfigureMacOS(IHostBuilder builder)
{
// Use launchd for macOS
_ = Signal(SIGSTOP, _ => HandlePause());
_ = Signal(SIGCONT, _ => HandleContinue());
_ = Signal(SIGHUP, _ => HandleRestart());

Signal(SIGTSTP, HandleSignalStop);
Signal(SIGCONT, HandleSignalContinue);
Signal(SIGHUP, HandleSignalRestart);
Signal(SIGTERM, HandleSignalTerminate);
builder.Build().Run();
}

Expand All @@ -156,92 +161,46 @@ private static void ConfigureWindows(IHostBuilder builder, string serviceName)
using var host = builder.Build();
var service = new PodeMonitorWindowsService(host, serviceName);
ServiceBase.Run(service);

}

/// <summary>
/// Handles the pause signal by pausing the Pode service.
/// </summary>
private static void HandlePause()
private static void HandleSignalStop(int signum)
{
if (_workerInstance == null)
{
PodeMonitorLogger.Log(LogLevel.ERROR, "PodeMonitor", Environment.ProcessId, "Pause requested, but _workerInstance is null.");
return;
}
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Pausing service...");
_workerInstance?.OnPause();
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "SIGTSTP received. Pausing service.");
HandlePause();
}

/// <summary>
/// Handles the continue signal by resuming the Pode service.
/// </summary>
private static void HandleContinue()
private static void HandleSignalTerminate(int signum)
{
if (_workerInstance == null)
{
PodeMonitorLogger.Log(LogLevel.ERROR, "PodeMonitor", Environment.ProcessId, "Continue requested, but _workerInstance is null.");
return;
}
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Resuming service...");
_workerInstance?.OnContinue();
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "SIGTERM received. Stopping service.");
HandleStop();
}

/// <summary>
/// Handles the restart signal by restarting the Pode service.
/// </summary>
private static void HandleRestart()
private static void HandleSignalContinue(int signum)
{
if (_workerInstance == null)
{
PodeMonitorLogger.Log(LogLevel.ERROR, "PodeMonitor", Environment.ProcessId, "Restart requested, but _workerInstance is null.");
return;
}
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Restarting service...");
_workerInstance?.Restart();
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "SIGCONT received. Resuming service.");
HandleContinue();
}

/// <summary>
/// Performs cleanup operations before service termination.
/// </summary>
private static void Cleanup()
private static void HandleSignalRestart(int signum)
{
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Performing cleanup...");
// Cleanup logic
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "SIGHUP received. Restarting service.");
HandleRestart();
}

private static void HandlePause() => _workerInstance?.OnPause();
private static void HandleContinue() => _workerInstance?.OnContinue();
private static void HandleRestart() => _workerInstance?.Restart();
private static void HandleStop() => _workerInstance?.Shutdown();
#else
/// <summary>
/// Configures the Pode service for Linux, including signal handling.
/// </summary>
/// <param name="builder">The host builder.</param>
[SupportedOSPlatform("Linux")]
private static void ConfigureLinux(IHostBuilder builder)
{
builder.UseSystemd();
builder.Build().Run();
}
[SupportedOSPlatform("linux")]
private static void ConfigureLinux(IHostBuilder builder) => builder.UseSystemd().Build().Run();

/// <summary>
/// Configures the Pode service for macOS, including signal handling.
/// </summary>
/// <param name="builder">The host builder.</param>
[SupportedOSPlatform("macOS")]
private static void ConfigureMacOS(IHostBuilder builder)
{
builder.Build().Run();
}

/// <summary>
/// Configures the Pode service for Windows, enabling pause and continue support.
/// </summary>
/// <param name="builder">The host builder.</param>
/// <param name="serviceName">The name of the service.</param>
private static void ConfigureWindows(IHostBuilder builder, string serviceName)
{
builder.UseWindowsService();
builder.Build().Run();
}
private static void ConfigureMacOS(IHostBuilder builder) => builder.Build().Run();

[SupportedOSPlatform("windows")]
private static void ConfigureWindows(IHostBuilder builder, string serviceName) =>
builder.UseWindowsService().Build().Run();
#endif
}
}
20 changes: 15 additions & 5 deletions src/PodeMonitor/PodeMonitorWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,31 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
/// </summary>
/// <param name="stoppingToken">Cancellation token to signal when the stop should occur.</param>
public override async Task StopAsync(CancellationToken stoppingToken)
{
Shutdown();

await base.StopAsync(stoppingToken); // Wait for the base StopAsync to complete

PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Service stopped successfully at: {0}", DateTimeOffset.Now);
}


/// <summary>
/// Shutdown the Pode PowerShell process by sending a shutdown command.
/// </summary>
public void Shutdown()
{
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Service is stopping at: {0}", DateTimeOffset.Now);

try
{
_pwshMonitor.StopPowerShellProcess(); // Stop the PowerShell process
_pwshMonitor.StopPowerShellProcess(); // Stop the process
PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Stop message sent via pipe at: {0}", DateTimeOffset.Now);
}
catch (Exception ex)
{
PodeMonitorLogger.Log(LogLevel.ERROR, ex, "Error stopping PowerShell process: {0}", ex.Message);
}

await base.StopAsync(stoppingToken); // Wait for the base StopAsync to complete

PodeMonitorLogger.Log(LogLevel.INFO, "PodeMonitor", Environment.ProcessId, "Service stopped successfully at: {0}", DateTimeOffset.Now);
}

/// <summary>
Expand Down
Loading

0 comments on commit d959b34

Please sign in to comment.