private static void Daemon(IMineContext mineContext, Action clear) { if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); _sDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _sDaemon = VirtualRoot.On <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Instance.CurrentMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount + 1; Logger.ErrorWriteLine(processName + $"挖矿内核进程消失"); if (Instance.MinerProfile.IsAutoRestartKernel && mineContext.AutoRestartKernelCount <= Instance.MinerProfile.AutoRestartKernelTimes) { Logger.WarnWriteLine($"尝试第{mineContext.AutoRestartKernelCount}次重启,共{Instance.MinerProfile.AutoRestartKernelTimes}次"); Instance.RestartMine(); Instance.CurrentMineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount; } else { Instance.StopMineAsync(); } if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); clear?.Invoke(); } } } } else { if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); clear?.Invoke(); } } }); }
private static void Daemon(IMineContext mineContext, Action clear) { string processName = mineContext.Kernel.GetProcessName(); Bus.DelegateHandler <Per1MinuteEvent> daemon = null; daemon = Global.Access <Per1MinuteEvent>( Guid.Parse("a4761e90-dc3c-4483-b055-546084863640"), "周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.None, action: message => { if (mineContext == Current.CurrentMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound + 1; Global.Logger.WarnWriteLine(processName + $"挖矿内核进程消失"); if (Current.MinerProfile.IsAutoRestartKernel && mineContext.ProcessDisappearedCound <= 3) { Global.Logger.WarnWriteLine($"尝试第{mineContext.ProcessDisappearedCound}次重启,共3次"); Current.RestartMine(); Current.CurrentMineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound; } else { Current.StopMine(); } Global.UnAccess(daemon); clear?.Invoke(); } } } else { Global.UnAccess(daemon); clear?.Invoke(); } }); }
// 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台 private static void CreatePipProcess(IMineContext mineContext, string kernelExeFileFullName, string arguments) { SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES { bInheritHandle = true, lpSecurityDescriptor = IntPtr.Zero, length = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)) }; //set the bInheritHandle flag so pipe handles are inherited saAttr.lpSecurityDescriptor = IntPtr.Zero; //get handle to current stdOut IntPtr mypointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STARTUPINFO))); Marshal.StructureToPtr(saAttr, mypointer, true); var bret = CreatePipe(out var hReadOut, out var hWriteOut, mypointer, 0); //ensure the read handle to pipe for stdout is not inherited SetHandleInformation(hReadOut, HANDLE_FLAG_INHERIT, 0); ////Create pipe for the child process's STDIN STARTUPINFO lpStartupInfo = new STARTUPINFO { cb = (uint)Marshal.SizeOf(typeof(STARTUPINFO)), dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW, wShowWindow = SW_HIDE, // SW_HIDE; //SW_SHOW hStdOutput = hWriteOut, hStdError = hWriteOut, hStdInput = IntPtr.Zero }; string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}"; Write.UserOk(cmdLine); Write.UserInfo("有请内核上场"); StringBuilder lpEnvironment = new StringBuilder(); // 复制父进程的环境变量 IDictionary dic = Environment.GetEnvironmentVariables(); // 追加环境变量 foreach (var item in mineContext.CoinKernel.EnvironmentVariables) { dic.Add(item.Key, item.Value); } foreach (var key in dic.Keys) { if (key == null || key.ToString().Contains("\0")) { continue; } var value = dic[key]; if (value == null || value.ToString().Contains("\0")) { continue; } lpEnvironment.Append($"{key.ToString()}={value.ToString()}\0"); } if (CreateProcess( lpApplicationName: null, lpCommandLine: new StringBuilder(cmdLine), lpProcessAttributes: IntPtr.Zero, lpThreadAttributes: IntPtr.Zero, bInheritHandles: true, dwCreationFlags: NORMAL_PRIORITY_CLASS, lpEnvironment: lpEnvironment, lpCurrentDirectory: Path.GetDirectoryName(kernelExeFileFullName), lpStartupInfo: ref lpStartupInfo, lpProcessInformation: out _)) { if (bret == false) { int lasterr = Marshal.GetLastWin32Error(); VirtualRoot.Happened(new StartingMineFailedEvent($"管道型进程创建失败 lasterr:{lasterr}")); } else { Bus.DelegateHandler <MineStopedEvent> closeHandle = null; bool isHWriteOutHasClosed = false; Daemon(mineContext, () => { if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } VirtualRoot.UnPath(closeHandle); }); closeHandle = VirtualRoot.On <MineStopedEvent>("挖矿停止后关闭非托管的日志句柄", LogEnum.DevConsole, action: message => { // 挖矿停止后摘除挖矿内核进程守护器 if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); _sDaemon = null; } if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } VirtualRoot.UnPath(closeHandle); }); string pipLogFileFullName = Path.Combine(SpecialPath.LogsDirFullName, mineContext.PipeFileName); Task.Factory.StartNew(() => { FileStream fs = new FileStream(pipLogFileFullName, FileMode.OpenOrCreate, FileAccess.ReadWrite); using (StreamReader sr = new StreamReader(fs)) { byte[] buffer = new byte[1024]; int ret; // Read会阻塞,直到读取到字符或者hWriteOut被关闭 while ((ret = Read(buffer, 0, buffer.Length, hReadOut)) > 0) { fs.Write(buffer, 0, ret); if (buffer[ret - 1] == '\r' || buffer[ret - 1] == '\n') { fs.Flush(); } } } CloseHandle(hReadOut); }, TaskCreationOptions.LongRunning); ReadPrintLoopLogFileAsync(mineContext, pipLogFileFullName); } } else { VirtualRoot.Happened(new StartingMineFailedEvent($"内核启动失败,请重试")); } }
// 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台 private static void CreatePipProcess(IMineContext mineContext, string cmdLine) { SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES(); IntPtr hReadOut, hWriteOut; //set the bInheritHandle flag so pipe handles are inherited saAttr.bInheritHandle = true; saAttr.lpSecurityDescriptor = IntPtr.Zero; saAttr.length = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)); saAttr.lpSecurityDescriptor = IntPtr.Zero; //get handle to current stdOut bool bret; IntPtr mypointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STARTUPINFO))); Marshal.StructureToPtr(saAttr, mypointer, true); bret = CreatePipe(out hReadOut, out hWriteOut, mypointer, 0); //ensure the read handle to pipe for stdout is not inherited SetHandleInformation(hReadOut, HANDLE_FLAG_INHERIT, 0); ////Create pipe for the child process's STDIN STARTUPINFO lpStartupInfo = new STARTUPINFO { cb = (uint)Marshal.SizeOf(typeof(STARTUPINFO)), dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW, wShowWindow = SW_HIDE, // SW_HIDE; //SW_SHOW hStdOutput = hWriteOut, hStdError = hWriteOut, hStdInput = IntPtr.Zero }; PROCESS_INFORMATION lpProcessInformation; if (CreateProcess( lpApplicationName: null, lpCommandLine: new StringBuilder(cmdLine), lpProcessAttributes: IntPtr.Zero, lpThreadAttributes: IntPtr.Zero, bInheritHandles: true, dwCreationFlags: NORMAL_PRIORITY_CLASS, lpEnvironment: IntPtr.Zero, lpCurrentDirectory: null, lpStartupInfo: ref lpStartupInfo, lpProcessInformation: out lpProcessInformation)) { if (bret == false) { int lasterr = Marshal.GetLastWin32Error(); } else { Bus.DelegateHandler <MineStopedEvent> closeHandle = null; bool isHWriteOutHasClosed = false; Daemon(mineContext, () => { if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } Global.UnAccess(closeHandle); }); closeHandle = Global.Access <MineStopedEvent>( Guid.Parse("91642027-fd28-4bdd-a05a-31caac6609b1"), "挖矿停止后关闭非托管的日志句柄", LogEnum.Log, action: message => { if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } Global.UnAccess(closeHandle); }); string pipLogFileFullName = Path.Combine(SpecialPath.LogsDirFullName, mineContext.PipeFileName); Task.Factory.StartNew(() => { using (FileStream fs = new FileStream(pipLogFileFullName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) using (StreamReader sr = new StreamReader(fs)) { byte[] buffer = new byte[1024]; int ret; // Read会阻塞,直到读取到字符或者hWriteOut被关闭 while ((ret = Read(buffer, 0, buffer.Length, hReadOut)) > 0) { fs.Write(buffer, 0, ret); if (buffer[ret - 1] == '\r' || buffer[ret - 1] == '\n') { fs.Flush(); } } } CloseHandle(hReadOut); }); Task.Factory.StartNew(() => { ReadPrintLoopLogFile(mineContext, pipLogFileFullName); }); } } else { Global.Logger.WarnWriteLine("内核启动失败,请重试"); } }
// 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台 private static void CreatePipProcess(IMineContext mineContext, string cmdLine) { SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES { bInheritHandle = true, lpSecurityDescriptor = IntPtr.Zero, length = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)) }; //set the bInheritHandle flag so pipe handles are inherited saAttr.lpSecurityDescriptor = IntPtr.Zero; //get handle to current stdOut IntPtr mypointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STARTUPINFO))); Marshal.StructureToPtr(saAttr, mypointer, true); var bret = CreatePipe(out var hReadOut, out var hWriteOut, mypointer, 0); //ensure the read handle to pipe for stdout is not inherited SetHandleInformation(hReadOut, HANDLE_FLAG_INHERIT, 0); ////Create pipe for the child process's STDIN STARTUPINFO lpStartupInfo = new STARTUPINFO { cb = (uint)Marshal.SizeOf(typeof(STARTUPINFO)), dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW, wShowWindow = SW_HIDE, // SW_HIDE; //SW_SHOW hStdOutput = hWriteOut, hStdError = hWriteOut, hStdInput = IntPtr.Zero }; if (CreateProcess( lpApplicationName: null, lpCommandLine: new StringBuilder(cmdLine), lpProcessAttributes: IntPtr.Zero, lpThreadAttributes: IntPtr.Zero, bInheritHandles: true, dwCreationFlags: NORMAL_PRIORITY_CLASS, lpEnvironment: IntPtr.Zero, lpCurrentDirectory: SpecialPath.KernelsDirFullName, lpStartupInfo: ref lpStartupInfo, lpProcessInformation: out _)) { if (bret == false) { int lasterr = Marshal.GetLastWin32Error(); Write.UserLine($"管道型进程创建失败 lasterr:{lasterr}", ConsoleColor.Red); } else { Bus.DelegateHandler <MineStopedEvent> closeHandle = null; bool isHWriteOutHasClosed = false; Daemon(mineContext, () => { if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } VirtualRoot.UnPath(closeHandle); }); closeHandle = VirtualRoot.On <MineStopedEvent>("挖矿停止后关闭非托管的日志句柄", LogEnum.DevConsole, action: message => { // 挖矿停止后摘除挖矿内核进程守护器 if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); _sDaemon = null; } if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } VirtualRoot.UnPath(closeHandle); }); string pipLogFileFullName = Path.Combine(SpecialPath.LogsDirFullName, mineContext.PipeFileName); Task.Factory.StartNew(() => { FileStream fs = new FileStream(pipLogFileFullName, FileMode.OpenOrCreate, FileAccess.ReadWrite); using (StreamReader sr = new StreamReader(fs)) { byte[] buffer = new byte[1024]; int ret; // Read会阻塞,直到读取到字符或者hWriteOut被关闭 while ((ret = Read(buffer, 0, buffer.Length, hReadOut)) > 0) { fs.Write(buffer, 0, ret); if (buffer[ret - 1] == '\r' || buffer[ret - 1] == '\n') { fs.Flush(); } } } CloseHandle(hReadOut); }); ReadPrintLoopLogFileAsync(mineContext, pipLogFileFullName); } } else { Logger.ErrorWriteLine("内核启动失败,请重试"); } }