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)); }
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)); }
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)); }
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)); }