예제 #1
0
        protected override Task <int> ExecuteCoreAsync()
        {
            // Make sure there's only one server with the same identity at a time.
            using (var mutex = new Mutex(initiallyOwned: true, name: MutexName.GetServerMutexName(Pipe.Value()), createdNew: out var holdsMutex))
            {
                if (!holdsMutex)
                {
                    // Another server is running, just exit.
                    Error.Write("Another server already running...");
                    return(Task.FromResult(1));
                }

                try
                {
                    var host         = ConnectionHost.Create(Pipe.Value());
                    var compilerHost = CompilerHost.Create();
                    var dispatcher   = RequestDispatcher.Create(host, compilerHost, Cancelled);
                    dispatcher.Run();
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }

            return(Task.FromResult(0));
        }
예제 #2
0
            public DefaultRequestDispatcher(ConnectionHost connectionHost, CompilerHost compilerHost, CancellationToken cancellationToken)
            {
                _connectionHost    = connectionHost;
                _compilerHost      = compilerHost;
                _cancellationToken = cancellationToken;

                _eventBus  = EventBus.Default;
                _keepAlive = new KeepAlive(DefaultServerKeepAlive, isDefault: true);
            }
예제 #3
0
        protected override Task <int> ExecuteCoreAsync()
        {
            // Make sure there's only one server with the same identity at a time.
            var   serverMutexName = MutexName.GetServerMutexName(Pipe.Value());
            Mutex serverMutex     = null;
            var   holdsMutex      = false;

            try
            {
                serverMutex = new Mutex(initiallyOwned: true, name: serverMutexName, createdNew: out holdsMutex);
            }
            catch (Exception ex)
            {
                // The Mutex constructor can throw in certain cases. One specific example is docker containers
                // where the /tmp directory is restricted. In those cases there is no reliable way to execute
                // the server and we need to fall back to the command line.
                // Example: https://github.com/dotnet/roslyn/issues/24124

                Error.Write($"Server mutex creation failed. {ex.Message}");

                return(Task.FromResult(-1));
            }

            if (!holdsMutex)
            {
                // Another server is running, just exit.
                Error.Write("Another server already running...");
                return(Task.FromResult(1));
            }

            try
            {
                TimeSpan?keepAlive = null;
                if (KeepAlive.HasValue() && int.TryParse(KeepAlive.Value(), out var result))
                {
                    // Keep alive times are specified in seconds
                    keepAlive = TimeSpan.FromSeconds(result);
                }

                var host = ConnectionHost.Create(Pipe.Value());

                var compilerHost = CompilerHost.Create();
                ExecuteServerCore(host, compilerHost, Cancelled, eventBus: null, keepAlive: keepAlive);
            }
            finally
            {
                serverMutex.ReleaseMutex();
                serverMutex.Dispose();
            }

            return(Task.FromResult(0));
        }
예제 #4
0
 protected override void ExecuteServerCore(
     ConnectionHost host,
     CompilerHost compilerHost,
     CancellationToken cancellationToken,
     EventBus eventBus,
     TimeSpan?keepAlive = null)
 {
     base.ExecuteServerCore(
         _host ?? host,
         _compilerHost ?? compilerHost,
         _cancellationToken,
         _eventBus ?? eventBus,
         _keepAlive ?? keepAlive);
 }
예제 #5
0
 public TestableServerCommand(
     ConnectionHost host,
     CompilerHost compilerHost,
     CancellationToken ct,
     EventBus eventBus,
     TimeSpan?keepAlive)
     : base(new Application(ct))
 {
     _host              = host;
     _compilerHost      = compilerHost;
     _cancellationToken = ct;
     _eventBus          = eventBus;
     _keepAlive         = keepAlive;
 }
예제 #6
0
 public TestableServerCommand(
     ConnectionHost host,
     CompilerHost compilerHost,
     CancellationToken ct,
     EventBus eventBus,
     TimeSpan?keepAlive)
     : base(new Application(ct, Mock.Of <ExtensionAssemblyLoader>(), Mock.Of <ExtensionDependencyChecker>()))
 {
     _host              = host;
     _compilerHost      = compilerHost;
     _cancellationToken = ct;
     _eventBus          = eventBus;
     _keepAlive         = keepAlive;
 }
예제 #7
0
        internal static ServerData CreateServer(
            string pipeName                        = null,
            CompilerHost compilerHost              = null,
            ConnectionHost connectionHost          = null,
            Action <object, EventArgs> onListening = null)
        {
            pipeName       = pipeName ?? Guid.NewGuid().ToString();
            compilerHost   = compilerHost ?? CompilerHost.Create();
            connectionHost = connectionHost ?? ConnectionHost.Create(pipeName);

            var serverStatsSource  = new TaskCompletionSource <ServerStats>();
            var serverListenSource = new TaskCompletionSource <bool>();
            var cts       = new CancellationTokenSource();
            var mutexName = MutexName.GetServerMutexName(pipeName);
            var thread    = new Thread(_ =>
            {
                var eventBus        = new TestableEventBus();
                eventBus.Listening += (sender, e) => { serverListenSource.TrySetResult(true); };
                if (onListening != null)
                {
                    eventBus.Listening += (sender, e) => onListening(sender, e);
                }
                try
                {
                    RunServer(
                        pipeName,
                        connectionHost,
                        compilerHost,
                        cts.Token,
                        eventBus,
                        Timeout.InfiniteTimeSpan);
                }
                finally
                {
                    var serverStats = new ServerStats(connections: eventBus.ConnectionCount, completedConnections: eventBus.CompletedCount);
                    serverStatsSource.SetResult(serverStats);
                }
            });

            thread.Start();

            // The contract of this function is that it will return once the server has started.  Spin here until
            // we can verify the server has started or simply failed to start.
            while (ServerConnection.WasServerMutexOpen(mutexName) != true && thread.IsAlive)
            {
                Thread.Yield();
            }

            return(new ServerData(cts, pipeName, serverStatsSource.Task, serverListenSource.Task));
        }
예제 #8
0
        internal static int RunServer(
            string pipeName,
            ConnectionHost host,
            CompilerHost compilerHost,
            CancellationToken cancellationToken = default,
            EventBus eventBus  = null,
            TimeSpan?keepAlive = null)
        {
            var command = new TestableServerCommand(host, compilerHost, cancellationToken, eventBus, keepAlive);
            var args    = new List <string>
            {
                "-p",
                pipeName
            };

            var result = command.Execute(args.ToArray());

            return(result);
        }
        public DefaultRequestDispatcher(
            ConnectionHost connectionHost,
            CompilerHost compilerHost,
            CancellationToken cancellationToken,
            EventBus eventBus  = null,
            TimeSpan?keepAlive = null)
        {
            _connectionHost    = connectionHost;
            _compilerHost      = compilerHost;
            _cancellationToken = cancellationToken;

            _eventBus = eventBus ?? EventBus.Default;

            var keepAliveTimeout = DefaultServerKeepAlive;

            if (keepAlive.HasValue)
            {
                keepAliveTimeout = keepAlive.Value;
            }
            _keepAlive = new KeepAlive(keepAliveTimeout, isDefault: true);
        }
예제 #10
0
        protected override Task <int> ExecuteCoreAsync()
        {
            // Make sure there's only one server with the same identity at a time.
            using (var mutex = new Mutex(initiallyOwned: true, name: MutexName.GetServerMutexName(Pipe.Value()), createdNew: out var holdsMutex))
            {
                if (!holdsMutex)
                {
                    // Another server is running, just exit.
                    Error.Write("Another server already running...");
                    return(Task.FromResult(1));
                }

                try
                {
                    TimeSpan?keepAlive = null;
                    if (KeepAlive.HasValue())
                    {
                        var value = KeepAlive.Value();
                        if (int.TryParse(value, out var result))
                        {
                            // Keep alive times are specified in seconds
                            keepAlive = TimeSpan.FromSeconds(result);
                        }
                    }

                    var host = ConnectionHost.Create(Pipe.Value());

                    var compilerHost = CompilerHost.Create();
                    ExecuteServerCore(host, compilerHost, Cancelled, eventBus: null, keepAlive: keepAlive);
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }

            return(Task.FromResult(0));
        }
예제 #11
0
        protected virtual void ExecuteServerCore(ConnectionHost host, CompilerHost compilerHost, CancellationToken cancellationToken, EventBus eventBus, TimeSpan?keepAlive)
        {
            var dispatcher = RequestDispatcher.Create(host, compilerHost, cancellationToken, eventBus, keepAlive);

            dispatcher.Run();
        }
예제 #12
0
 public static RequestDispatcher Create(ConnectionHost connectionHost, CompilerHost compilerHost, CancellationToken cancellationToken, EventBus eventBus, TimeSpan?keepAlive = null)
 {
     return(new DefaultRequestDispatcher(connectionHost, compilerHost, cancellationToken, eventBus, keepAlive));
 }
예제 #13
0
 public static RequestDispatcher Create(ConnectionHost connectionHost, CompilerHost compilerHost, CancellationToken cancellationToken)
 {
     return(new DefaultRequestDispatcher(connectionHost, compilerHost, cancellationToken));
 }