Esempio n. 1
0
 /// <summary>
 /// Changes <see cref="DesiredRunningState"/> to Stop and sends Cancel token to all miners that need to be stopped
 /// </summary>
 public virtual void StopMining()
 {
     Logger.Info(_logGroup, $"Stop miner called");
     lock (_lock)
     {
         _desiredState = DesiredRunningState.Stop;
         Logger.Info(_logGroup, $"Stop miner called: STOP TASKS IN LIST: {_stopMiners.Count}");
         foreach (var stopMiner in _stopMiners)
         {
             try
             {
                 stopMiner?.Cancel();
             }
             catch (Exception e)
             {
                 Logger.Error(_logGroup, $"Error occured while StopMining: {e.Message}");
             }
         }
     }
 }
Esempio n. 2
0
        // TODO check mining pairs
        /// <summary>
        /// Sets <see cref="DesiredRunningState"/> to Start if not already so. Then creates a miningProcess and awaits for stop token. Also handles restarts of miningProcess in case of errors.
        /// </summary>
        public void StartMining()
        {
            lock (_lock)
            {
                if (_desiredState == DesiredRunningState.Start)
                {
                    Logger.Error(_logGroup, $"Trying to start an already started miner");
                    return;
                }
                Logger.Info(_logGroup, $"Starting miner watchdog task");
                _desiredState = DesiredRunningState.Start;
            }

            //const int ERROR_FILE_NOT_FOUND = 0x2;
            //const int ERROR_ACCESS_DENIED = 0x5;
            Task.Run(() =>
            {
                using (var stopMiner = new CancellationTokenSource())
                {
                    lock (_lock)
                    {
                        _stopMiners.Add(stopMiner);
                    }
                    var run = IsStart() && stopMiner.IsCancellationRequested == false;
                    while (run)
                    {
                        var binPathBinCwdPair    = GetBinAndCwdPaths();
                        var binPath              = binPathBinCwdPair.Item1;
                        var binCwd               = binPathBinCwdPair.Item2;
                        var commandLine          = MiningCreateCommandLine();
                        var environmentVariables = GetEnvironmentVariables();

                        using (var miningProcess = MinerToolkit.CreateMiningProcess(binPath, binCwd, commandLine, environmentVariables))
                        {
                            lock (_lock)
                            {
                                _miningProcess = miningProcess;
                            }
                            var quitMiningProcess = stopMiner.Token.Register(() =>
                            {
                                try
                                {
                                    var pid = miningProcess?.Id ?? -1;
                                    miningProcess?.CloseMainWindow();
                                    // 5 seconds wait for shutdown
                                    var hasExited    = !miningProcess?.WaitForExit(5 * 1000) ?? false;
                                    var stillRunning = pid > -1 ? Process.GetProcessById(pid) != null : false;
                                    if (!hasExited || stillRunning)
                                    {
                                        miningProcess?.Kill(); // TODO look for another gracefull shutdown
                                    }
                                }
                                catch (Exception e)
                                {
                                    Logger.Info(_logGroup, $"Error occured while stopping the process: {e.Message}");
                                }
                            });
                            try
                            {
                                // mandatory 500ms delay
                                Task.Delay(500).Wait();

                                // BEFORE
                                ThrowIfIsStop(stopMiner.IsCancellationRequested);
                                if (this is IBeforeStartMining bsm)
                                {
                                    bsm.BeforeStartMining();
                                }
                                ThrowIfIsStop(stopMiner.IsCancellationRequested);

                                // Logging
                                Logger.Info(_logGroup, $"Starting miner binPath='{binPath}'");
                                Logger.Info(_logGroup, $"Starting miner binCwd='{binCwd}'");
                                Logger.Info(_logGroup, $"Starting miner commandLine='{commandLine}'");
                                // TODO this will not print content
                                var environmentVariablesLog = environmentVariables == null ? "<null>" : string.Join(";", environmentVariables.Select(x => x.Key + "=" + x.Value));
                                Logger.Info(_logGroup, $"Starting miner environmentVariables='{environmentVariablesLog}'"); // TODO log or debug???
                                ThrowIfIsStop(stopMiner.IsCancellationRequested);
                                //_stopMiner = new CancellationTokenSource();
                                {
                                    if (!miningProcess.Start())
                                    {
                                        Logger.Info(_logGroup, $"Error occured while starting a new process: {miningProcess.ToString()}");
                                        throw new InvalidOperationException("Could not start process: " + miningProcess);
                                    }

                                    ThrowIfIsStop(stopMiner.IsCancellationRequested);
                                    if (this is IAfterStartMining asm)
                                    {
                                        asm.AfterStartMining();
                                    }
                                    ThrowIfIsStop(stopMiner.IsCancellationRequested);

                                    // block loop until process is running
                                    miningProcess.WaitForExit();
                                }
                            }
                            //catch (Win32Exception ex2)
                            //{
                            //    ////if (ex2.NativeErrorCode == ERROR_FILE_NOT_FOUND) throw ex2;
                            //    //Logger.Info(_logGroup, $"Win32Exception Error occured in StartMining : {ex2.ToString()}");
                            //    //Task.Delay(MinerToolkit.MinerRestartDelayMS, _stopMiner.Token).Wait();
                            //}
                            catch (StopMinerWatchdogException)
                            {
                                Logger.Info(_logGroup, $"Watchdog stopped in StartMining");
                            }
                            catch (Exception e)
                            {
                                Logger.Error(_logGroup, $"Error occured in StartMining : {e.Message}");
                            }
                            finally
                            {
                                quitMiningProcess.Dispose();
                                // delay restart
                                run = IsStart() && stopMiner.IsCancellationRequested == false;
                                if (run)
                                {
                                    Logger.Info(_logGroup, $"Restart Mining in {MinerToolkit.MinerRestartDelayMS}ms");
                                    Task.Delay(MinerToolkit.MinerRestartDelayMS).Wait();
                                }
                            }
                        }
                    }
                    Logger.Info(_logGroup, $"Exited miner watchdog");
                    lock (_lock)
                    {
                        _stopMiners.Remove(stopMiner);
                    }
                }
            });
        }