public void ConnectToServerFails()
            {
                // Create and grab the mutex for the server. This should make
                // the client believe that a server is active and it will try
                // to connect. When it fails it should fall back to in-proc
                // compilation.
                bool holdsMutex;

                using (var serverMutex = new Mutex(initiallyOwned: true,
                                                   name: BuildProtocolConstants.GetServerMutexName(_pipeName),
                                                   createdNew: out holdsMutex))
                {
                    Assert.True(holdsMutex);
                    var ranLocal = false;
                    // Note: Connecting to a server can take up to a second to time out
                    var client = CreateClient(
                        compileFunc: delegate
                    {
                        ranLocal = true;
                        return(0);
                    });
                    var exitCode = client.RunCompilation(new[] { "/shared" }, _buildPaths).ExitCode;
                    Assert.Equal(0, exitCode);
                    Assert.True(ranLocal);
                }
            }
Beispiel #2
0
 internal static BuildRequest CreateEmptyCSharpWithKeepAlive(TimeSpan keepAlive, string workingDirectory, string tempDirectory = null) => BuildRequest.Create(
     RequestLanguage.CSharpCompile,
     Array.Empty <string>(),
     workingDirectory,
     tempDirectory ?? Path.GetTempPath(),
     compilerHash: BuildProtocolConstants.GetCommitHash(),
     keepAlive: keepAlive.TotalSeconds.ToString());
Beispiel #3
0
        internal static ServerData CreateServer(
            string pipeName  = null,
            TimeSpan?timeout = null,
            ICompilerServerHost compilerServerHost = null)
        {
            pipeName           = pipeName ?? Guid.NewGuid().ToString();
            compilerServerHost = compilerServerHost ?? new DesktopCompilerServerHost(DefaultClientDirectory, DefaultSdkDirectory);

            var taskSource = new TaskCompletionSource <ServerStats>();
            var cts        = new CancellationTokenSource();
            var thread     = new Thread(_ =>
            {
                var listener = new TestableDiagnosticListener();
                try
                {
                    var clientConnectionHost = new NamedPipeClientConnectionHost(compilerServerHost, pipeName);
                    var mutexName            = BuildProtocolConstants.GetServerMutexName(pipeName);
                    VBCSCompiler.Run(
                        mutexName,
                        clientConnectionHost,
                        listener,
                        timeout ?? TimeSpan.FromMilliseconds(-1),
                        cts.Token);
                }
                finally
                {
                    var serverStats = new ServerStats(connections: listener.ConnectionCount, completedConnections: listener.CompletedCount);
                    taskSource.SetResult(serverStats);
                }
            });

            thread.Start();

            return(new ServerData(cts, taskSource.Task, pipeName));
        }
Beispiel #4
0
        public async Task RejectEmptyTempPath()
        {
            using var temp       = new TempRoot();
            using var serverData = await ServerUtil.CreateServer(Logger);

            var request = BuildRequest.Create(
                RequestLanguage.CSharpCompile,
                workingDirectory: temp.CreateDirectory().Path,
                tempDirectory: null,
                compilerHash: BuildProtocolConstants.GetCommitHash(),
                libDirectory: null,
                args: Array.Empty <string>()
                );
            var response = await serverData.SendAsync(request);

            Assert.Equal(ResponseType.Rejected, response.Type);
        }
            public async Task ServerShutdownsDuringProcessing()
            {
                using (var readyMre = new ManualResetEvent(initialState: false))
                    using (var doneMre = new ManualResetEvent(initialState: false))
                    {
                        var  pipeName  = Guid.NewGuid().ToString();
                        var  mutexName = BuildProtocolConstants.GetServerMutexName(pipeName);
                        bool created   = false;
                        bool connected = false;

                        var thread = new Thread(() =>
                        {
                            using (var stream = new NamedPipeServerStream(pipeName))
                            {
                                var mutex = new Mutex(initiallyOwned: true, name: mutexName, createdNew: out created);
                                readyMre.Set();

                                stream.WaitForConnection();
                                connected = true;

                                // Client is waiting for a response.  Close the mutex now.  Then close the connection
                                // so the client gets an error.
                                mutex.ReleaseMutex();
                                mutex.Dispose();
                                stream.Close();

                                doneMre.WaitOne();
                            }
                        });

                        // Block until the mutex and named pipe is setup.
                        thread.Start();
                        readyMre.WaitOne();

                        var exitCode = await VBCSCompiler.RunShutdownAsync(pipeName, waitForProcess : false);

                        // Let the fake server exit.
                        doneMre.Set();
                        thread.Join();

                        Assert.Equal(CommonCompiler.Succeeded, exitCode);
                        Assert.True(connected);
                        Assert.True(created);
                    }
            }
Beispiel #6
0
        public async Task <ConnectionData> HandleConnection(bool allowCompilationRequests = true, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                BuildRequest request;
                try
                {
                    Log("Begin reading request.");
                    request = await BuildRequest.ReadAsync(_stream, cancellationToken).ConfigureAwait(false);

                    ValidateBuildRequest(request);
                    Log("End reading request.");
                }
                catch (Exception e)
                {
                    LogException(e, "Error reading build request.");
                    return(new ConnectionData(CompletionReason.CompilationNotStarted));
                }

                if (request.ProtocolVersion != BuildProtocolConstants.ProtocolVersion)
                {
                    return(await HandleMismatchedVersionRequest(cancellationToken).ConfigureAwait(false));
                }
                else if (!string.Equals(request.CompilerHash, BuildProtocolConstants.GetCommitHash(), StringComparison.OrdinalIgnoreCase))
                {
                    return(await HandleIncorrectHashRequest(cancellationToken).ConfigureAwait(false));
                }
                else if (IsShutdownRequest(request))
                {
                    return(await HandleShutdownRequest(cancellationToken).ConfigureAwait(false));
                }
                else if (!allowCompilationRequests)
                {
                    return(await HandleRejectedRequest(cancellationToken).ConfigureAwait(false));
                }
                else
                {
                    return(await HandleCompilationRequest(request, cancellationToken).ConfigureAwait(false));
                }
            }
            finally
            {
                Close();
            }
        }
Beispiel #7
0
        private async Task <BuildRequest> CreateBuildRequest(
            string sourceText,
            TimeSpan?keepAlive = null
            )
        {
            var directory = Temp.CreateDirectory();
            var file      = directory.CreateFile("temp.cs");
            await file.WriteAllTextAsync(sourceText);

            var builder = ImmutableArray.CreateBuilder <BuildRequest.Argument>();

            if (keepAlive.HasValue)
            {
                builder.Add(
                    new BuildRequest.Argument(
                        BuildProtocolConstants.ArgumentId.KeepAlive,
                        argumentIndex: 0,
                        value: keepAlive.Value.TotalSeconds.ToString()
                        )
                    );
            }

            builder.Add(
                new BuildRequest.Argument(
                    BuildProtocolConstants.ArgumentId.CurrentDirectory,
                    argumentIndex: 0,
                    value: directory.Path
                    )
                );
            builder.Add(
                new BuildRequest.Argument(
                    BuildProtocolConstants.ArgumentId.CommandLineArgument,
                    argumentIndex: 0,
                    value: file.Path
                    )
                );

            return(new BuildRequest(
                       RequestLanguage.CSharpCompile,
                       BuildProtocolConstants.GetCommitHash(),
                       builder.ToImmutable()
                       ));
        }
            public async Task NoServerConnection()
            {
                using (var readyMre = new ManualResetEvent(initialState: false))
                    using (var doneMre = new ManualResetEvent(initialState: false))
                    {
                        var  pipeName  = Guid.NewGuid().ToString();
                        var  mutexName = BuildProtocolConstants.GetServerMutexName(pipeName);
                        bool created   = false;
                        bool connected = false;

                        var thread = new Thread(() =>
                        {
                            using (var mutex = new Mutex(initiallyOwned: true, name: mutexName, createdNew: out created))
                                using (var stream = new NamedPipeServerStream(pipeName))
                                {
                                    readyMre.Set();

                                    // Get a client connection and then immediately close it.  Don't give any response.
                                    stream.WaitForConnection();
                                    connected = true;
                                    stream.Close();

                                    doneMre.WaitOne();
                                    mutex.ReleaseMutex();
                                }
                        });

                        // Block until the mutex and named pipe is setup.
                        thread.Start();
                        readyMre.WaitOne();

                        var exitCode = await VBCSCompiler.RunShutdownAsync(pipeName, waitForProcess : false);

                        // Let the fake server exit.
                        doneMre.Set();
                        thread.Join();

                        Assert.Equal(CommonCompiler.Failed, exitCode);
                        Assert.True(connected);
                        Assert.True(created);
                    }
            }
Beispiel #9
0
        /// <summary>
        /// Create a compiler server that fails all connections.
        /// </summary>
        internal static ServerData CreateServerFailsConnection(string pipeName = null)
        {
            pipeName = pipeName ?? Guid.NewGuid().ToString();

            var taskSource = new TaskCompletionSource <ServerStats>();
            var cts        = new CancellationTokenSource();

            using (var mre = new ManualResetEvent(initialState: false))
            {
                var thread = new Thread(_ =>
                {
                    var mutexName = BuildProtocolConstants.GetServerMutexName(pipeName);
                    bool holdsMutex;
                    using (var serverMutex = new Mutex(initiallyOwned: true,
                                                       name: mutexName,
                                                       createdNew: out holdsMutex))
                    {
                        mre.Set();
                        if (!holdsMutex)
                        {
                            throw new InvalidOperationException("Mutex should be unique");
                        }

                        var connections = CreateServerFailsConnectionCore(pipeName, cts.Token).Result;
                        taskSource.SetResult(new ServerStats(connections: connections, completedConnections: 0));
                    }
                });

                thread.Start();

                // Can't exit until the mutex is acquired.  Otherwise the client can end up in a race
                // condition trying to start the server.
                mre.WaitOne();
            }

            return(new ServerData(cts, taskSource.Task, pipeName));
        }
Beispiel #10
0
 internal static BuildRequest CreateEmptyCSharp(string workingDirectory, string tempDirectory = null) => BuildRequest.Create(
     RequestLanguage.CSharpCompile,
     Array.Empty <string>(),
     workingDirectory,
     tempDirectory ?? Path.GetTempPath(),
     compilerHash: BuildProtocolConstants.GetCommitHash());
Beispiel #11
0
 internal static BuildRequest CreateEmptyCSharpWithKeepAlive(TimeSpan keepAlive) => BuildRequest.Create(
     RequestLanguage.CSharpCompile,
     Array.Empty <string>(),
     compilerHash: BuildProtocolConstants.GetCommitHash(),
     keepAlive: keepAlive.TotalSeconds.ToString());