/// <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}"); } } } }
// 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); } } }); }