private static async Task Loop(TcpConnectorSlave connector, ModuleBase module) { Process parentProcess = null; using (Request request = await connector.ReceiveRequest()) { if (request.Code != ModuleHelper.ID_ParentInfo) { throw new Exception("Missing ParentInfo request (update MediatorLib.dll)"); } ParentInfoMsg info = StdJson.ObjectFromUtf8Stream <ParentInfoMsg>(request.Payload); parentProcess = Process.GetProcessById(info.PID); connector.SendResponseSuccess(request.RequestID, s => { }); } Thread t = new Thread(() => { ParentAliveChecker(parentProcess); }); t.IsBackground = true; t.Start(); var helper = new ModuleHelper(module, connector); bool run = true; while (run) { using (Request request = await connector.ReceiveRequest()) { helper.ExecuteModuleRequestAsync(request); bool shutdown = request.Code == ModuleHelper.ID_Shutdown; bool initAbort = request.Code == ModuleHelper.ID_InitAbort; run = !shutdown && !initAbort; } } // Wait until parent process kills us (after Run method completed) while (true) { await Task.Delay(1000); } }
public override async Task Init(ModuleInitInfo info, VariableValue[] restoreVariableValues, Notifier notifier, ModuleThread moduleThread) { this.moduleName = info.ModuleName; this.notifier = notifier; logger = LogManager.GetLogger(info.ModuleName); var config = info.GetConfigReader(); string cmd = config.GetString("ExternalCommand"); string args = config.GetString("ExternalArgs"); const string portPlaceHolder = "{PORT}"; if (!args.Contains(portPlaceHolder)) { throw new Exception("Missing port placeholder in args parameter: {PORT}"); } var server = TcpConnectorServer.ListenOnFreePort(); int port = server.Port; args = args.Replace(portPlaceHolder, port.ToString()); const string releaseDebugPlaceHolder = "{RELEASE_OR_DEBUG}"; if (args.Contains(releaseDebugPlaceHolder)) { #if DEBUG args = args.Replace(releaseDebugPlaceHolder, "Debug"); #else args = args.Replace(releaseDebugPlaceHolder, "Release"); #endif } try { var taskConnect = server.WaitForConnect(TimeSpan.FromSeconds(60)); process = StartProcess(cmd, args); while (!process.HasExited && !taskConnect.IsCompleted) { await Task.Delay(TimeSpan.FromMilliseconds(50)); } if (process.HasExited) { throw new Exception($"Failed to start command \"{cmd}\" with arguments \"{args}\""); } connection = await taskConnect; var parentInfo = new ParentInfoMsg() { PID = Process.GetCurrentProcess().Id }; Task ignored = SendVoidRequest(parentInfo); var initMsg = new InitOrThrowMsg() { InitInfo = info, RestoreVariableValues = restoreVariableValues }; Task tInit = SendVoidRequest(initMsg); taskReceive = connection.ReceiveAndDistribute(onEvent); Task t = await Task.WhenAny(tInit, taskReceive); if (t != tInit) { if (process.HasExited) { throw new Exception("Module process terminated during Init call."); } else { throw new Exception("TCP connection broken to Module process during Init call."); } } await tInit; } catch (Exception) { if (connection != null) { connection.Close("Init failed."); } StopProcess(process); process = null; throw; } finally { server.StopListening(); } }