public Task StopAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (Proc != null && !Proc.HasExited)
                {
                    Proc.Kill();
                    Proc.WaitForExit(10000);

                    Proc.Close();
                    Proc.Dispose();
                    Proc = null;
                }
            }
            catch (Exception e)
            {
                Logger.Error("Stop", e);
            }
            return(Task.CompletedTask);
        }
 private void StopNode()
 {
     try
     {
         if (Proc != null && !Proc.HasExited)
         {
             Proc.Kill();
             if (!Proc.WaitForExit(10000)) /* wait 10 seconds */
             {
                 Logger.Warn("The process does not wait for completion.");
             }
             Proc.Close();
             Proc.Dispose();
             Proc = null;
         }
     }
     catch (Exception e)
     {
         Logger.Error("SocketIO failed stop", e);
     }
 }
Example #3
0
 private void StopRadicale()
 {
     try
     {
         if (Proc != null && !Proc.HasExited)
         {
             Proc.Kill();
             if (!Proc.WaitForExit(10000))
             {
                 Logger.Warn("The process does not wait for completion.");
             }
             Proc.Close();
             Proc.Dispose();
             Proc = null;
         }
     }
     catch (Exception e)
     {
         Logger.Error("Radicale failed stop", e);
     }
 }
Example #4
0
        public virtual void Run()
        {
            //_success = false; //initial state to be defined by each inheriting class depending on it's handlers, we only update error conditions in this routine
            Process  Proc = null;
            DateTime ExecutionStartTime;

            // Last thing to check, for custom commands, this will log an error and exit
            if (!File.Exists(_ApplicationPath))
            {
                _jobStatus.ErrorMsg = "Application File Not Found";
                _jobLog.WriteEntry(this, _jobStatus.ErrorMsg + " : " + _ApplicationPath, Log.LogEntryType.Error);
                _jobStatus.PercentageComplete = 0;
                _success = false;
                return;
            }

            if (_Parameters.Length > 8192)
            {
                _jobLog.WriteEntry(this, Localise.GetPhrase("Warning - command parameters exceeding 8192 characters.  This may fail on some systems such as Windows XP"), Log.LogEntryType.Warning);
            }

            // Reset any progress counters
            _jobStatus.PercentageComplete = 0;
            _jobStatus.ETA = Localise.GetPhrase("Working") + "..."; //some processes like ReMuxSupp don't update perc, put a default message

            // Check if job has been cancelled, needed for some long running functions called Base
            if (_jobStatus.Cancelled)
            {
                _jobStatus.ErrorMsg = "Job cancelled, killing process";
                _jobLog.WriteEntry(this, _jobStatus.ErrorMsg, Log.LogEntryType.Error);
                _success = false; //process has been terminated
                return;
            }

            try
            {
                if (_HangPeriod > 0)
                {
                    _LastTick = DateTime.Now;
                }

                _jobLog.WriteEntry(this, "Launching process " + _ApplicationPath, Log.LogEntryType.Debug);
                _jobLog.WriteEntry(this, "Process arguments " + _Parameters, Log.LogEntryType.Debug);

                if (GlobalDefs.IsEngineRunningAsService) // these params only make sense when running as a service
                {
                    _jobLog.WriteEntry(this, "UI Session Admin Process : " + _uiAdminSessionProcess.ToString(), Log.LogEntryType.Debug);
                }

                //Start the process
                ExecutionStartTime = DateTime.Now;

                // Check if we need to run a UISession process - It can only be run from a service, if we are running from a non service console, we don't need this
                // Apps like handbrake with hardware accelleration cannot run from a non UI session in windows (even in Windows 8 there are limitations with ffmpeg and OpenCL from Session 0) due to unavailability of hardware (OpenCL) API's in NonUI sessions mode
                // These apps needs to be started in a UI session separately to run
                // Check if we are running as a Service (Session 0 non UI Interactive) and if the user forcing use of UI Session 1
                bool checkUICompliance = (GlobalDefs.IsEngineRunningAsService && _uiAdminSessionProcess);
                if (checkUICompliance)
                {
                    _jobLog.WriteEntry(this, "Starting process as a UISession process with Admin privileges. This requires atleast 1 user to be logged into the system (remote desktop or locally)", Log.LogEntryType.Debug);
                    uint procId = AppProcess.StartAppWithAdminPrivilegesFromNonUISession(_ApplicationPath, _Parameters, true, OutputHandler, _showWindow, _jobLog);
                    if (procId == 0)
                    {
                        _jobLog.WriteEntry(this, "Unable to create UI Session process with Admin Privileges from NonUI Session. Is any user logged on?", Log.LogEntryType.Warning);
                        _jobLog.WriteEntry(this, "Retrying process creation as a NonUI Session process with Admin privileges", Log.LogEntryType.Warning);
                        _jobLog.WriteEntry(this, "Some functions like hardware encoding may not work in this mode", Log.LogEntryType.Warning);
                        Proc = null;
                    }
                    else
                    {
                        Proc = Process.GetProcessById((int)procId); // Get the process identifier
                    }
                }

                // Create the process if it hasn't already been created
                if (Proc == null)
                {
                    //Set up the process
                    Proc = new Process();
                    Proc.StartInfo.FileName  = _ApplicationPath;
                    Proc.StartInfo.Arguments = _Parameters;
                    if (_showWindow)
                    {
                        Proc.StartInfo.CreateNoWindow = false; // for custom apps we create a window
                        Proc.StartInfo.WindowStyle    = ProcessWindowStyle.Normal;
                    }
                    else
                    {
                        Proc.StartInfo.CreateNoWindow = true;
                        Proc.StartInfo.WindowStyle    = ProcessWindowStyle.Hidden;
                    }
                    Proc.StartInfo.WorkingDirectory       = Path.GetDirectoryName(_ApplicationPath);
                    Proc.StartInfo.RedirectStandardOutput = true;
                    Proc.StartInfo.RedirectStandardError  = true;
                    Proc.StartInfo.UseShellExecute        = false; // always false else error handlers break
                    Proc.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
                    Proc.ErrorDataReceived  += new DataReceivedEventHandler(OutputHandler);

                    Proc.Start(); // First start the process else we get an exception
                    Proc.BeginOutputReadLine();
                    Proc.BeginErrorReadLine();
                }
            }
            catch (Exception Ex)
            {
                _jobStatus.ErrorMsg = "Unable to start process";
                _jobLog.WriteEntry(this, _jobStatus.ErrorMsg + "\r\n" + Ex.Message, Log.LogEntryType.Error);
                _success = false; //process did not start
                return;           // Exit now or we get an exception
            }

            // NOTE: Do all this after starting the process outside the catch block. Sometimes the process exists quickly (e.g. when process priority is IDLE) before this code runs and hence this code throws an exception
            try
            {
                _jobLog.WriteEntry(this, "Setting process priority to " + GlobalDefs.Priority.ToString(), Log.LogEntryType.Debug);
                Proc.PriorityClass = GlobalDefs.Priority;                   // Set the CPU Priority
                IOPriority.SetPriority(Proc.Handle, GlobalDefs.IOPriority); // Set the IO Priority

                if (MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity != (IntPtr)0)
                {
                    _jobLog.WriteEntry(this, "Setting CPU affinity to -> " + MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity.ToString("d"), Log.LogEntryType.Debug);
                    Proc.ProcessorAffinity = MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity;
                }
            }
            catch (Exception e)
            {
                _jobLog.WriteEntry(this, "Error trying process priority or setting CPU affinity to -> " + MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity.ToString("d") + "\n" + e.ToString(), Log.LogEntryType.Warning);
            }

            //Wait for an end
            while ((!Proc.HasExited))
            {
                try
                {
                    if (!_ignoreSuspend)                      // for some processes like ffmpegMediaInfo initiated by UI, we cannot block since it will hang the application
                    {
                        if (!isSuspended && GlobalDefs.Pause) // Check if process has to be suspended (if not already)
                        {
                            _jobLog.WriteEntry(this, "Suspending process", Log.LogEntryType.Information);
                            IOPriority.SuspendProcess(Proc.Id);
                            _jobLog.Flush(); // Flush the pending writes
                            isSuspended = true;
                        }

                        if (isSuspended && !GlobalDefs.Pause) // Check if we need to resume the process
                        {
                            _jobLog.WriteEntry(this, "Resuming process", Log.LogEntryType.Information);
                            isSuspended = false;
                            _percentageHistory.Clear(); // Lose the history and start from here
                            IOPriority.ResumeProcess(Proc.Id);
                        }
                    }

                    if (Proc.PriorityClass != GlobalDefs.Priority) // Check if the priority was changed and if so update it
                    {
                        _jobLog.WriteEntry(this, "Process priority changed to " + GlobalDefs.Priority.ToString(), Log.LogEntryType.Information);
                        Proc.PriorityClass = GlobalDefs.Priority;
                        IOPriority.SetPriority(Proc.Handle, GlobalDefs.IOPriority); // First set the CPU priority
                    }
                }
                catch { } //incase process exits in the background - not an issue, just avoid a crash

                if (_jobStatus.Cancelled) // if job has been cancelled kill the process
                {
                    try
                    {
                        Proc.Kill();
                        _jobStatus.ErrorMsg = "Job cancelled, killing process";
                        _jobLog.WriteEntry(_jobStatus.ErrorMsg, Log.LogEntryType.Error);
                        _success = false; //process has been terminated
                    }
                    catch (Exception Ex)
                    {
                        _jobStatus.ErrorMsg = "Job cancelled, unable to kill process";
                        _jobLog.WriteEntry(_jobStatus.ErrorMsg, Log.LogEntryType.Error);
                        _jobLog.WriteEntry(Ex.Message, Log.LogEntryType.Warning);
                        _success = false; //process has been terminated
                    }
                    break;
                }

                if (_unrecoverableError)
                {
                    _jobLog.WriteEntry("Unrecoverable error encountered. Process likely hung, killing it", Log.LogEntryType.Error);
                    _success = false;
                    break;
                }

                if (isSuspended)
                {
                    _LastTick = DateTime.Now; // Since during suspension there will be no output it shouldn't terminate the process
                }
                if ((_HangPeriod > 0) && (DateTime.Now > _LastTick.AddSeconds(_HangPeriod)))
                {
                    _jobLog.WriteEntry("No response from process for " + _HangPeriod + " seconds, process likely hung - killing it", Log.LogEntryType.Error);
                    _success = false;
                    break;
                }

                System.Threading.Thread.Sleep(100); // sleep and check again
            }

            if (!_jobStatus.Cancelled)
            {
                System.Threading.Thread.Sleep(2000); //Allow the last set of messages to be written
            }
            if (!Proc.HasExited)                     // If we broke out of the loop, somethign bad happened
            {
                try
                {
                    Proc.Kill();
                    _jobStatus.ErrorMsg = "Process hung, killing process";
                    _jobLog.WriteEntry(_jobStatus.ErrorMsg, Log.LogEntryType.Error);
                    _success = false; //process has been terminated
                }
                catch (Exception Ex)
                {
                    _jobStatus.ErrorMsg = "Unable to terminate process";
                    _jobLog.WriteEntry(_jobStatus.ErrorMsg + "\r\n" + Ex.Message, Log.LogEntryType.Error);
                    _success = false; //process has been terminated
                }
            }
            else
            {
                // Sometimes for some reason the process exits without the output redirect async handlers completing causing failures
                // MSDN http://msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx recommends using WaitForExit(x) followed by WaitForExit() to flush all output async handlers
                // TODO: Aysnc output is broken in .NET even with WaitForExit(), see http://alabaxblog.info/2013/06/redirectstandardoutput-beginoutputreadline-pattern-broken/ and http://stackoverflow.com/questions/9533070/how-to-read-to-end-process-output-asynchronously-in-c
                try
                {
                    while (!Proc.WaitForExit(10))
                    {
                        ;               // Wait for it to return True
                    }
                    Proc.WaitForExit(); // Now wait for it to flush the buffers
                }
                catch { }

                _exitCode = Proc.ExitCode; // Store the exit code
                _jobLog.WriteEntry("Process exited with code " + _exitCode.ToString(), Log.LogEntryType.Debug);
            }


            _ExecutionTime = DateTime.Now - ExecutionStartTime;

            //Close out
            try
            {
                Proc.Close();
                Proc.Dispose();
            }
            catch (Exception Ex)
            {
                _jobLog.WriteEntry("Unable to cleanly close process" + "\r\n" + Ex.Message, Log.LogEntryType.Error);
            }

            Proc = null;

            if (!_jobStatus.Cancelled)
            {
                System.Threading.Thread.Sleep(100);    //Allow for the process to be flush any pending messages
            }
        }