Exemplo n.º 1
0
 public static IDisposable RegisterWaitForSingleObject(WaitHandle handle, Action<object, bool> callback, object state, TimeSpan timeout)
 {
     var ret = new CancelWaitHandle();
     Task.Run(() =>
     {
         var result = WaitHandle.WaitAny(new[] { handle, ret.WaitHandle }, timeout);
         ret.SetCallbackThreadId(Environment.CurrentManagedThreadId);
         if (result == WaitHandle.WaitTimeout)
             callback(state, true);
         else if (result == 0)
             callback(state, false);
         ret.CallbackCompleted();
     });
     return ret;
 }
Exemplo n.º 2
0
        public static IDisposable RegisterWaitForSingleObject(WaitHandle handle, Action <object, bool> callback, object state, TimeSpan timeout)
        {
            var ret = new CancelWaitHandle();

            Task.Run(() =>
            {
                var result = WaitHandle.WaitAny(new[] { handle, ret.WaitHandle }, timeout);
                ret.SetCallbackThreadId(Environment.CurrentManagedThreadId);
                if (result == WaitHandle.WaitTimeout)
                {
                    callback(state, true);
                }
                else if (result == 0)
                {
                    callback(state, false);
                }
                ret.CallbackCompleted();
            });
            return(ret);
        }
Exemplo n.º 3
0
            public void Run()
            {
                if (_alreadyStarted)
                {
                    throw new InvalidOperationException("Can't run again.");
                }

                var sw = Stopwatch.StartNew();

                _alreadyStarted = true;

                Process.Start();
                if (!ShouldIgnoreConsoleOutput)
                {
                    Process.BeginOutputReadLine();
                    Process.BeginErrorReadLine();
                }

                while (!Process.WaitForExit(1000))
                {
                    if (MaxWorkingSetMb > 0)
                    {
                        long peakWorkingSet = 0;
                        try
                        {
                            if (!Process.HasExited)
                            {
                                Process.Refresh();
                                peakWorkingSet = Process.PeakWorkingSet64;
                            }
                        }
                        catch (InvalidOperationException)
                        {
                        }

                        if (peakWorkingSet > (MaxWorkingSetMb * 1024 * 1024))
                        {
                            _log.LogInformation("Attempting to kill process since it exceeded it's maximum working set size");
                            try
                            {
                                if (!Process.HasExited)
                                {
                                    Process.Kill();

                                    // Wait for up to a minute so the process can release it's resources
                                    Process.WaitForExit(60000);
                                }
                            }
                            catch (Win32Exception)
                            {
                            }
                            catch (InvalidOperationException)
                            {
                            }

                            throw new InvalidOperationException(
                                      $"Process {Process.ProcessName} exceeded working set limit. Process WS:{Process.WorkingSet64}. Limit:{Process.MaxWorkingSet}");
                        }
                    }

                    if (MaxAllowedRuntimeInMinutes > 0)
                    {
                        if (sw.Elapsed.TotalMinutes > MaxAllowedRuntimeInMinutes)
                        {
                            _log.LogInformation("Attempting to kill process since it exceeded it's max allowed run time ({0} minutes)", MaxAllowedRuntimeInMinutes);
                            try
                            {
                                if (!Process.HasExited)
                                {
                                    Process.Kill();

                                    // Wait for up to a minute so the process can release it's resources
                                    Process.WaitForExit(60000);
                                }
                            }
                            catch (Win32Exception)
                            {
                            }
                            catch (InvalidOperationException)
                            {
                            }

                            throw new InvalidOperationException($"Process exceeded max allowed run time ({MaxAllowedRuntimeInMinutes} minutes)");
                        }
                    }

                    if (MaxVirtualMemorySizeMb > 0)
                    {
                        long peakVirtualMemorySize = 0;
                        try
                        {
                            if (!Process.HasExited)
                            {
                                Process.Refresh();
                                peakVirtualMemorySize = Process.PeakVirtualMemorySize64;
                            }
                        }
                        catch (InvalidOperationException)
                        {
                        }

                        if (peakVirtualMemorySize > (MaxVirtualMemorySizeMb * 1024 * 1024))
                        {
                            _log.LogInformation("Attempting to kill process since it exceeded the configured Virtual memory limit");
                            try
                            {
                                if (!Process.HasExited)
                                {
                                    Process.Kill();

                                    // Wait for up to a minute so the process can release it's resources
                                    Process.WaitForExit(60000);
                                }
                            }
                            catch (Win32Exception)
                            {
                            }
                            catch (InvalidOperationException)
                            {
                            }

                            throw new InvalidOperationException(
                                      $"Process {FileName} exceeded Virtual memory limit. Process VM Size:{peakVirtualMemorySize / (1024 * 1024)} MB. Limit:{MaxVirtualMemorySizeMb} MB");
                        }
                    }

                    if (CancelWaitHandle != null && CancelWaitHandle.WaitOne(0))
                    {
                        _log.LogInformation("Attempting to kill process since cancelWaitHandle is set");
                        try
                        {
                            if (!Process.HasExited)
                            {
                                Process.Kill();
                            }
                        }
                        catch (Win32Exception)
                        {
                        }
                        catch (InvalidOperationException)
                        {
                        }

                        throw new OperationCanceledException();
                    }
                }

                // Note that earlier, we called Process.WaitForExit(1000).
                // https://msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx
                // According to msdn documentation, that overload has a caveat:
                //   When standard output has been redirected to asynchronous event handlers,
                //   it is possible that output processing will not have completed when this method returns.
                //   To ensure that asynchronous event handling has been completed,
                //   call the WaitForExit() overload that takes no parameter after receiving a true
                //   from this overload. To help ensure that the Exited event is handled correctly
                //   in Windows Forms applications, set the SynchronizingObject property.
                // Hence, we call the overload with no parameter here.
                Process.WaitForExit();

                lock (_syncObject)
                {
                    StandardOutput = _sbStdOut.ToString();
                    StandardError  = _sbStdErr.ToString();
                }

                ExitCode = Process.ExitCode;
            }