Example #1
0
        /// <summary>
        /// Ensures the monitoring process is restarted if it crashed.
        /// </summary>
        /// <param name="parameter">The monitoring process.</param>
        private static void ExecuteSymmetricWatch(object?parameter)
        {
            // Wait a bit to ensure the new process is started.
            // A proper synchronization would be preferable, but at this point I'm too lazy.
            Thread.Sleep(1000);

            Monitoring Monitoring = (Monitoring)parameter !;

            Debug.Assert(Monitoring.MonitorProcess != null);
            Debug.Assert(Monitoring.CancelEvent != null);

#pragma warning disable CS8604 // Possible null reference argument.
            ExecuteSymmetricWatch(Monitoring, Monitoring.MonitorProcess, Monitoring.CancelEvent);
#pragma warning restore CS8604 // Possible null reference argument.
        }
Example #2
0
        /// <summary>
        /// Installs the monitor.
        /// </summary>
        /// <returns>True if successful; False otherwise and <see cref="LastError"/> contains the error.</returns>
        public bool ZombifyMe()
        {
            Monitoring NewMonitoring = new Monitoring()
            {
                ClientName = ClientName, Delay = Delay, WatchingMessage = WatchingMessage, RestartMessage = RestartMessage, Flags = Flags, IsSymmetric = IsSymmetric, AliveTimeout = AliveTimeout, MonitorFolder = MonitorFolder
            };

            Debug.Assert(NewMonitoring.CancelEvent == null);

            bool Result = ZombifyMeInternal(NewMonitoring, out Errors Error);

            CancelEvent = NewMonitoring.CancelEvent;
            LastError   = Error;

            return(Result);
        }
Example #3
0
        /// <summary>
        /// Ensures the monitoring process is restarted if it crashed.
        /// </summary>
        /// <param name="monitoring">The monitoring information.</param>
        /// <param name="monitorProcess">The monitoring process.</param>
        /// <param name="cancelEvent">The cancellation event.</param>
        private static void ExecuteSymmetricWatch(Monitoring monitoring, Process monitorProcess, EventWaitHandle cancelEvent)
        {
            TimeSpan AliveTimeout = monitoring.AliveTimeout;

            Debug.Assert(AliveTimeout > TimeSpan.Zero);

            bool IsAlive = true;

            AliveWatch.Start();

            while (IsAlive)
            {
                if (AliveWatch.Elapsed >= AliveTimeout)
                {
                    break;
                }

                if (cancelEvent.WaitOne(SharedDefinitions.CheckInterval))
                {
                    break;
                }

                IsAlive = !monitorProcess.HasExited;

                if (!IsAlive)
                {
                    using (monitorProcess)
                    {
                    }

                    // Wait the same delay as if restarting the original process.
                    Thread.Sleep(monitoring.Delay);

                    ZombifyMeInternal(monitoring, out _);
                }
            }
        }
Example #4
0
        /// <summary>
        /// Starts a thread to ensure the monitoring process is restarted if it crashed.
        /// </summary>
        /// <param name="monitoring">Monitoring parameters.</param>
        private static void StartSymmetricWatch(Monitoring monitoring)
        {
            Thread NewThread = new Thread(ExecuteSymmetricWatch);

            NewThread.Start(monitoring);
        }
Example #5
0
        private static bool ZombifyMeInternal(Monitoring monitoring, out Errors error)
        {
            error = Errors.Success;

            if (!LoadMonitor(monitoring.MonitorFolder, out string MonitorProcessFileName))
            {
                error = Errors.UnableToLoadSource;
                return(false);
            }

#if NET48
            int ProcessId = Process.GetCurrentProcess().Id;
#else
            int ProcessId = Environment.ProcessId;
#endif

            Contracts.Contract.RequireNotNull(Assembly.GetEntryAssembly(), out Assembly EntryAssembly);
            string ClientExePath = EntryAssembly.Location;

            string ArgsText = string.Empty;
            if (monitoring.Flags.HasFlag(Flags.ForwardArguments))
            {
                // Accumulate arguments in a single string.
                string[] Args = Environment.GetCommandLineArgs();
                for (int Index = 1; Index < Args.Length; Index++)
                {
                    string Arg = Args[Index];
                    if (ArgsText.Length > 0)
                    {
                        ArgsText += " ";
                    }

                    ArgsText += Arg;
                }
            }

            long DelayTicks = monitoring.Delay.Ticks;

            monitoring.CancelEvent = new EventWaitHandle(false, EventResetMode.ManualReset, SharedDefinitions.GetCancelEventName(monitoring.ClientName));

            // Use this impossible value as a hack to fail the launch.
            if (monitoring.Delay == TimeSpan.MinValue)
            {
                MonitorProcessFileName = string.Empty;
            }

            // Start the monitoring process.
            // Don't dispose of it, it's passed to another thread.
            Process MonitorProcess = new Process
            {
                StartInfo =
                {
                    FileName        = MonitorProcessFileName,
                    Arguments       = $"{ProcessId} \"{ClientExePath}\" \"{ArgsText}\" \"{monitoring.ClientName}\" {DelayTicks} \"{monitoring.WatchingMessage}\" \"{monitoring.RestartMessage}\" {(int)monitoring.Flags}",
                    UseShellExecute = false,
                    CreateNoWindow  = true,
                },
            };

            bool Result;

            try
            {
                Result = MonitorProcess.Start();
            }
            catch
            {
                Result = false;
            }

            if (!Result)
            {
                error = Errors.MonitorNotStarted;
                monitoring.MonitorProcess = null;
            }
            else
            {
                monitoring.MonitorProcess = MonitorProcess;

                if (monitoring.IsSymmetric && monitoring.AliveTimeout > TimeSpan.Zero)
                {
                    StartSymmetricWatch(monitoring);
                }
            }

            return(Result);
        }