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);
            }
        }
示例#2
0
        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();
            }
        }