public IContainerHostClient StartContainerHost(string containerId, IContainerDirectory directory, JobObject jobObject, NetworkCredential credentials) { CopyHostToContainer(directory); var hostRunSpec = new ProcessRunSpec { ExecutablePath = directory.MapBinPath(dependencyHelper.ContainerHostExe), Arguments = new[] { containerId }, BufferedInputOutput = true, WorkingDirectory = directory.UserPath, Credentials = credentials, }; // Order here is important. // - Start the process // - Add the process to the job object // - Verify that the process is healthy // - Start the RPC message pump // // We need to ensure that the host process cannot create any new processes before // it's added to the job object. var hostProcess = processRunner.Run(hostRunSpec); jobObject.AssignProcessToJob(hostProcess.Handle); WaitForProcessToStart(hostProcess, HostProcessStartTimeout); var messageTransport = MessageTransport.Create(hostProcess.StandardOutput, hostProcess.StandardInput); var messagingClient = MessagingClient.Create(async message => { await messageTransport.PublishRequestAsync(message); }); messageTransport.SubscribeResponse(message => { messagingClient.PublishResponse(message); return(Task.FromResult(0)); }); messageTransport.SubscribeEvent(@event => { try { messagingClient.PublishEvent(@event); } catch (Exception e) { log.Log(LogLevel.Error, e.ToString(), e); } return(Task.FromResult(0)); }); var containerHostClient = new ContainerHostClient(hostProcess, messageTransport, messagingClient, jobObject); messageTransport.Start(); return(containerHostClient); }