From 207fbbbcc3caa2a05e915220c11c420da5f3075d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 27 Sep 2013 17:09:21 -0400 Subject: [PATCH] allow service to restart itself --- MediaBrowser.Mono.userprefs | 7 +- MediaBrowser.Server.Mono/Program.cs | 2 +- MediaBrowser.Server.Mono/app.config | 2 +- MediaBrowser.ServerApplication/MainStartup.cs | 187 +++++++++++------- 4 files changed, 124 insertions(+), 74 deletions(-) diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index 88bdb45e72..a12059af5e 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -2,10 +2,9 @@ - - - - + + + diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index ff3f2ae46a..86001887ea 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.Server.Mono private static ServerApplicationPaths CreateApplicationPaths() { - return new ServerApplicationPaths("D:\\MonoTest"); + return new ServerApplicationPaths(); } private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager) diff --git a/MediaBrowser.Server.Mono/app.config b/MediaBrowser.Server.Mono/app.config index 0f00424972..843dae41d6 100644 --- a/MediaBrowser.Server.Mono/app.config +++ b/MediaBrowser.Server.Mono/app.config @@ -7,7 +7,7 @@ - + diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 97563d1333..75f2a8f286 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -5,31 +5,28 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations; using Microsoft.Win32; using System; +using System.ComponentModel; using System.Configuration.Install; using System.Diagnostics; using System.IO; using System.Linq; using System.ServiceProcess; -using System.Threading; using System.Windows; namespace MediaBrowser.ServerApplication { public class MainStartup { - /// - /// The single instance mutex - /// - private static Mutex _singleInstanceMutex; - private static ApplicationHost _appHost; private static App _app; - private static BackgroundService _backgroundService; - private static ILogger _logger; + private static bool _isRestarting = false; + + private static bool _isRunningAsService = false; + /// /// Defines the entry point of the application. /// @@ -37,9 +34,9 @@ namespace MediaBrowser.ServerApplication public static void Main() { var startFlag = Environment.GetCommandLineArgs().ElementAtOrDefault(1); - var runService = string.Equals(startFlag, "-service", StringComparison.OrdinalIgnoreCase); + _isRunningAsService = string.Equals(startFlag, "-service", StringComparison.OrdinalIgnoreCase); - var appPaths = CreateApplicationPaths(runService); + var appPaths = CreateApplicationPaths(_isRunningAsService); var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Info); @@ -82,15 +79,12 @@ namespace MediaBrowser.ServerApplication AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - bool createdNew; + RunServiceInstallationIfNeeded(); - var runningPath = Process.GetCurrentProcess().MainModule.FileName.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty); + var currentProcess = Process.GetCurrentProcess(); - _singleInstanceMutex = new Mutex(true, @"Local\" + runningPath, out createdNew); - - if (!createdNew) + if (IsAlreadyRunning(currentProcess)) { - _singleInstanceMutex = null; logger.Info("Shutting down because another instance of Media Browser Server is already running."); return; } @@ -103,18 +97,49 @@ namespace MediaBrowser.ServerApplication try { - RunApplication(appPaths, logManager, runService); + RunApplication(appPaths, logManager, _isRunningAsService); } finally { - logger.Info("Shutting down"); - - ReleaseMutex(logger); - - _appHost.Dispose(); + OnServiceShutdown(); } } + /// + /// Determines whether [is already running] [the specified current process]. + /// + /// The current process. + /// true if [is already running] [the specified current process]; otherwise, false. + private static bool IsAlreadyRunning(Process currentProcess) + { + var runningPath = Process.GetCurrentProcess().MainModule.FileName; + + var duplicate = Process.GetProcesses().FirstOrDefault(i => + { + try + { + return string.Equals(runningPath, i.MainModule.FileName) && currentProcess.Id != i.Id; + } + catch (Win32Exception) + { + return false; + } + }); + + if (duplicate != null) + { + _logger.Info("Found a duplicate process. Giving it time to exit."); + + if (!duplicate.WaitForExit(5000)) + { + _logger.Info("The duplicate process did not exit."); + return true; + } + } + + return false; + } + /// /// Creates the application paths. /// @@ -159,8 +184,6 @@ namespace MediaBrowser.ServerApplication { SystemEvents.SessionEnding += SystemEvents_SessionEnding; - var commandLineArgs = Environment.GetCommandLineArgs(); - _appHost = new ApplicationHost(appPaths, logManager); _app = new App(_appHost, _appHost.LogManager.GetLogger("App"), runService); @@ -178,20 +201,11 @@ namespace MediaBrowser.ServerApplication /// private static void StartService(ILogManager logManager) { - var ctl = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName == BackgroundService.Name); - - if (ctl == null) - { - RunServiceInstallation(); - } - var service = new BackgroundService(logManager.GetLogger("Service")); service.Disposed += service_Disposed; ServiceBase.Run(service); - - _backgroundService = service; } /// @@ -199,9 +213,27 @@ namespace MediaBrowser.ServerApplication /// /// The source of the event. /// The instance containing the event data. - static async void service_Disposed(object sender, EventArgs e) + static void service_Disposed(object sender, EventArgs e) { - await _appHost.Shutdown(); + OnServiceShutdown(); + } + + private static void OnServiceShutdown() + { + _logger.Info("Shutting down"); + + _appHost.Dispose(); + + if (_isRestarting) + { + using (var process = Process.Start("cmd", "/c net start " + BackgroundService.Name)) + { + } + + _logger.Info("New service process started"); + } + + _app.Dispatcher.Invoke(_app.Shutdown); } /// @@ -242,6 +274,16 @@ namespace MediaBrowser.ServerApplication } } + private static void RunServiceInstallationIfNeeded() + { + var ctl = ServiceController.GetServices().FirstOrDefault(s => s.ServiceName == BackgroundService.Name); + + if (ctl == null) + { + RunServiceInstallation(); + } + } + /// /// Runs the service installation. /// @@ -299,7 +341,7 @@ namespace MediaBrowser.ServerApplication /// The instance containing the event data. static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) { - if (e.Reason == SessionEndReasons.SystemShutdown || _backgroundService == null) + if (e.Reason == SessionEndReasons.SystemShutdown || !_isRunningAsService) { Shutdown(); } @@ -316,7 +358,7 @@ namespace MediaBrowser.ServerApplication _logger.ErrorException("UnhandledException", exception); - if (_backgroundService == null) + if (!_isRunningAsService) { _app.OnUnhandledException(exception); } @@ -327,24 +369,6 @@ namespace MediaBrowser.ServerApplication } } - /// - /// Releases the mutex. - /// - internal static void ReleaseMutex(ILogger logger) - { - if (_singleInstanceMutex == null) - { - return; - } - - logger.Debug("Releasing mutex"); - - _singleInstanceMutex.ReleaseMutex(); - _singleInstanceMutex.Close(); - _singleInstanceMutex.Dispose(); - _singleInstanceMutex = null; - } - /// /// Performs the update if needed. /// @@ -378,40 +402,67 @@ namespace MediaBrowser.ServerApplication public static void Shutdown() { - if (_backgroundService != null) + if (_isRunningAsService) { - _backgroundService.Stop(); + ShutdownWindowsService(); } else { - _app.Dispatcher.Invoke(_app.Shutdown); + ShutdownWindowsApplication(); } } public static void Restart() { - // Second instance will start first, so release the mutex and dispose the http server ahead of time - _app.Dispatcher.Invoke(() => ReleaseMutex(_logger)); - + _logger.Info("Disposing app host"); _appHost.Dispose(); + _logger.Info("Starting new instance of server"); RestartInternal(); - _app.Dispatcher.Invoke(_app.Shutdown); + _logger.Info("Shutting down existing instance of server."); + Shutdown(); } private static void RestartInternal() { - if (_backgroundService == null) + if (!_isRunningAsService) { - System.Windows.Forms.Application.Restart(); + _logger.Info("Starting server application"); + RestartWindowsApplication(); } else { - //var controller = new ServiceController() - //{ - // ServiceName = BackgroundService.Name - //}; + _logger.Info("Starting windows service"); + RestartWindowsService(); + } + } + + private static void RestartWindowsApplication() + { + System.Windows.Forms.Application.Restart(); + } + + private static void RestartWindowsService() + { + _isRestarting = true; + } + + private static void ShutdownWindowsApplication() + { + _app.Dispatcher.Invoke(_app.Shutdown); + } + + private static void ShutdownWindowsService() + { + _logger.Info("Stopping background service"); + var service = new ServiceController(BackgroundService.Name); + + service.Refresh(); + + if (service.Status == ServiceControllerStatus.Running) + { + service.Stop(); } } }