public IProcess StartHost(Interpreter interpreter, string profilePath, string userName, ClaimsPrincipal principal, string commandLine)
        {
            var exeLocator  = BrokerExecutableLocator.Create(_fs);
            var hostBinPath = exeLocator.GetHostExecutablePath();

            if (!_fs.FileExists(hostBinPath) && RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                hostBinPath = PathConstants.RunHostBinPath;
            }

            var process = Utility.RunAsCurrentUser(_sessionLogger, _ps, hostBinPath, commandLine, GetRHomePath(interpreter), GetLoadLibraryPath(interpreter));

            process.WaitForExit(250);
            if (process.HasExited && process.ExitCode != 0)
            {
                var message = _ps.MessageFromExitCode(process.ExitCode);
                if (!string.IsNullOrEmpty(message))
                {
                    throw new Win32Exception(message);
                }
                throw new Win32Exception(process.ExitCode);
            }

            return(process);
        }
        public void Empty()
        {
            var locator = new BrokerExecutableLocator(_fs, OSPlatform.Windows);

            locator.GetBrokerExecutablePath().Should().BeNull();
            locator.GetHostExecutablePath().Should().BeNull();
        }
        public IProcess StartHost(string interpreterPath, string interpreterArchitecture, string commandLine)
        {
            var exeLocator = new BrokerExecutableLocator(_fs);

            var hostBinPath = exeLocator.GetHostExecutablePath(interpreterArchitecture);

            if (hostBinPath == null)
            {
                throw new Win32Exception($"Microsoft.R.Host is missing. Interpreter: {interpreterPath}. Architecture: {interpreterArchitecture}");
            }

            var psi = new ProcessStartInfo {
                FileName               = hostBinPath,
                Arguments              = commandLine,
                RedirectStandardError  = true,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                WorkingDirectory       = Environment.GetEnvironmentVariable("PWD")
            };

            psi.Environment.Add("R_HOME", interpreterPath);
            psi.Environment.Add("LD_LIBRARY_PATH", Path.Combine(interpreterPath, "lib"));

            var process = _ps.Start(psi);

            process.WaitForExit(250);
            if (process.HasExited && process.ExitCode != 0)
            {
                throw new Win32Exception(process.ExitCode);
            }
            return(process);
        }
        public void Duplicate()
        {
            var locator     = new BrokerExecutableLocator(_fs, OSPlatform.Windows);
            var brokerPath1 = Path.Combine(locator.BaseDirectory, BrokerExecutableLocator.WindowsBrokerName);
            var brokerPath2 = Path.Combine(locator.BaseDirectory, @"Broker\Windows\" + BrokerExecutableLocator.WindowsBrokerName);

            _fs.FileExists(brokerPath1).Returns(true);
            _fs.FileExists(brokerPath2).Returns(true);
            locator.GetBrokerExecutablePath().Should().Be(brokerPath2);
        }
Example #5
0
        private async Task ConnectToBrokerWorkerAsync(CancellationToken cancellationToken)
        {
            Trace.Assert(_brokerProcess == null);
            var fs      = _services.FileSystem();
            var locator = new BrokerExecutableLocator(fs);

            var rhostBrokerExe = locator.GetBrokerExecutablePath();

            // _services.UI().LogMessage($"R Host broker: {rhostBrokerExe}");
            if (!fs.FileExists(rhostBrokerExe))
            {
                throw new RHostBrokerBinaryMissingException();
            }

            IProcess process = null;

            try {
                var pipeName = Guid.NewGuid().ToString();
                var cts      = new CancellationTokenSource(Debugger.IsAttached ? 500000 : 100000);

                using (var processConnectCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token))
                    using (var serverUriPipe = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)) {
                        var psi = GetProcessStartInfo(rhostBrokerExe, pipeName);
                        // _services.UI().LogMessage($"Starting R Host broker: {rhostBrokerExe}");
                        process         = StartBroker(psi);
                        process.Exited += delegate {
                            cts.Cancel();
                            _brokerProcess = null;
                            _connectLock.EnqueueReset();
                        };

                        var uri = await GetBrokerUri(serverUriPipe, processConnectCts.Token, cts.Token);

                        CreateHttpClient(uri);
                    }

                if (DisposableBag.TryAdd(DisposeBrokerProcess))
                {
                    _brokerProcess = process;
                }
            } catch (Exception ex) {
                _services.UI().LogMessage($"Unable to start R Host broker process. Exception {ex.Message}");
                throw;
            } finally {
                if (_brokerProcess == null)
                {
                    try {
                        process?.Kill();
                    } catch (Exception) {
                    } finally {
                        process?.Dispose();
                    }
                }
            }
        }
Example #6
0
        public async Task RHostPipeFuzzTest(int iteration)
        {
            var input = GenerateInput();

            var locator      = BrokerExecutableLocator.Create(new WindowsFileSystem());
            var rhostExePath = locator.GetHostExecutablePath();
            var arguments    = Invariant($"--rhost-name \"FuzzTest\" --rhost-r-dir \"{_interpreter.BinPath}\"");

            var psi = new ProcessStartInfo(rhostExePath)
            {
                UseShellExecute        = false,
                CreateNoWindow         = false,
                Arguments              = arguments,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                RedirectStandardError  = true,
                LoadUserProfile        = true
            };
            var shortHome = new StringBuilder(1024);

            GetShortPathName(_interpreter.Path, shortHome, shortHome.Capacity);
            psi.EnvironmentVariables["R_HOME"] = shortHome.ToString();
            psi.EnvironmentVariables["PATH"]   = _interpreter.BinPath + ";" + Environment.GetEnvironmentVariable("PATH");

            psi.WorkingDirectory = Path.GetDirectoryName(rhostExePath);

            var process = new Process {
                StartInfo           = psi,
                EnableRaisingEvents = true,
            };

            process.Start();
            process.WaitForExit(250);

            // Process should not exit before fully starting up
            process.HasExited.Should().BeFalse();
            try {
                var killRhostTask = Task.Delay(3000).ContinueWith(t => TryKill(process));

                var cts = new CancellationTokenSource(3000);
                await ReadStartupOutputFromRHostAsync(process.StandardOutput.BaseStream, cts.Token);
                await SendFuzzedInputToRHostAsync(process.StandardInput.BaseStream, input, cts.Token);

                var readOutputTask = ReadAnyOutputFromRHostAsync(process.StandardOutput.BaseStream, cts.Token);
                // Fuzzed input should not kill the host.
                process.HasExited.Should().BeFalse();

                await Task.WhenAll(killRhostTask, readOutputTask);
            } finally {
                // In case anything fails above kill host.
                TryKill(process);
            }
        }
        private void TestPlatform(string brokerSubPath, string hostSubPath, OSPlatform platform)
        {
            var locator    = new BrokerExecutableLocator(_fs, platform);
            var brokerPath = Path.Combine(locator.BaseDirectory, brokerSubPath);
            var hostPath   = Path.Combine(locator.BaseDirectory, hostSubPath);

            _fs.FileExists(brokerPath).Returns(true);
            locator.GetBrokerExecutablePath().Should().Be(brokerPath);
            locator.GetHostExecutablePath().Should().BeNull();

            _fs.FileExists(hostPath).Returns(true);
            locator.GetBrokerExecutablePath().Should().Be(brokerPath);
            locator.GetHostExecutablePath().Should().Be(hostPath);
        }
Example #8
0
        public IProcess StartHost(Interpreter interpreter, string commandLine)
        {
            var exeLocator  = BrokerExecutableLocator.Create(_fs);
            var hostBinPath = exeLocator.GetHostExecutablePath();

            if (!_fs.FileExists(hostBinPath) && RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                hostBinPath = PathConstants.RunHostBinPath;
            }

            var process = Utility.RunAsCurrentUser(_ps, hostBinPath, commandLine, GetRHomePath(interpreter), GetLoadLibraryPath(interpreter));

            process.WaitForExit(250);
            if (process.HasExited && process.ExitCode != 0)
            {
                throw new Win32Exception(process.ExitCode);
            }
            return(process);
        }
Example #9
0
        private async Task <string> GetRemoteRtvsPackagePath(IRExpressionEvaluator eval)
        {
            var isWindows = await eval.IsRSessionPlatformWindowsAsync();

            if (!isWindows)
            {
                // Remote Linux
                return("/usr/share/rtvs");
            }
            // Check if there is 'rtvs' folder on remote
            var rtvsExists = await eval.FileExistsAsync("./rtvs/NAMESPACE");

            if (rtvsExists)
            {
                return(".");
            }
            // Most probably tests are running remote broker locally
            var locator       = BrokerExecutableLocator.Create(_fileSystem);
            var hostDirectory = Path.GetDirectoryName(locator.GetHostExecutablePath());

            rtvsExists = _fileSystem.FileExists(Path.Combine(hostDirectory, @"rtvs\NAMESPACE"));
            return(rtvsExists ? hostDirectory : Path.GetFullPath(Path.Combine(hostDirectory, @"..\..")));
        }
Example #10
0
        protected override string GetRHostBinaryPath()
        {
            var locator = BrokerExecutableLocator.Create(_fs);

            return(locator.GetHostExecutablePath());
        }
        public IProcess StartHost(Interpreter interpreter, string profilePath, string userName, ClaimsPrincipal principal, string commandLine)
        {
            var locator      = BrokerExecutableLocator.Create(new WindowsFileSystem());
            var rhostExePath = locator.GetHostExecutablePath();

            commandLine = FormattableString.Invariant($"\"{rhostExePath}\" {commandLine}");
            var usernameBldr = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1);
            var domainBldr   = new StringBuilder(NativeMethods.CREDUI_MAX_DOMAIN_LENGTH + 1);

            // Get R_HOME value
            var shortHome = new StringBuilder(NativeMethods.MAX_PATH);

            NativeMethods.GetShortPathName(interpreter.InstallPath, shortHome, shortHome.Capacity);

            var useridentity = principal.Identity as WindowsIdentity;
            var loggedOnUser = useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User;

            // build user environment block
            Win32EnvironmentBlock eb;

            if (loggedOnUser)
            {
                var error = NativeMethods.CredUIParseUserName(userName, usernameBldr, usernameBldr.Capacity, domainBldr, domainBldr.Capacity);
                if (error != 0)
                {
                    _sessionLogger.LogError(Resources.Error_UserNameParse, userName, error);
                    throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(userName, error));
                }

                var username = usernameBldr.ToString();
                var domain   = domainBldr.ToString();

                eb = CreateEnvironmentBlockForUser(useridentity, username, profilePath);

                // add globally set environment variables
                AddGlobalREnvironmentVariables(eb);
            }
            else
            {
                eb = Win32EnvironmentBlock.Create((useridentity ?? WindowsIdentity.GetCurrent()).Token);
            }

            // add additional variables to the environment block
            eb["R_HOME"] = shortHome.ToString();
            _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "R_HOME", eb["R_HOME"]);
            eb["PATH"] = FormattableString.Invariant($"{interpreter.BinPath};{Environment.GetEnvironmentVariable("PATH")}");
            _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "PATH", eb["PATH"]);

            Win32Process win32Process;

            using (var nativeEnv = eb.GetNativeEnvironmentBlock()) {
                if (loggedOnUser)
                {
                    win32Process = Win32Process.StartProcessAsUser(useridentity, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv);
                }
                else
                {
                    win32Process = Win32Process.StartProcessAsUser(null, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv);
                }
            }

            win32Process.Exited += (s, e) => {
            };

            win32Process.WaitForExit(250);
            if (win32Process.HasExited && win32Process.ExitCode < 0)
            {
                var message = ErrorCodeConverter.MessageFromErrorCode(win32Process.ExitCode);
                if (!string.IsNullOrEmpty(message))
                {
                    throw new Win32Exception(message);
                }
                throw new Win32Exception(win32Process.ExitCode);
            }

            return(win32Process);
        }