Repository: dotnet/roslyn
File: src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs (C#)

Code before:
        Console.WriteLine(JsonSerializer.Serialize(new NamedPipeInformation(clientPipeName)));

        // Wait for connection from client
        await pipeServer.WaitForConnectionAsync(cancellationToken);

        server = new LanguageServerHost(pipeServer, pipeServer, exportProvider, loggerFactory, typeRefResolver);
    }

    server.Start();

    logger.LogInformation("Language server initialized");
    RoslynLog.Logger.Log(RoslynLog.FunctionId.VSCode_LanguageServer_Started, logLevel: RoslynLog.LogLevel.Information);

    try
    {
        if (serverConfiguration.ParentProcessId is int parentProcessId)
        {
            logger.LogInformation("Monitoring parent process {parentProcessId} for exit", parentProcessId);
            var serverExitTask = server.WaitForExitAsync();
            var parentProcessExitTask = WaitForParentProcessExitAsync(parentProcessId, logger);
            var completedTask = await Task.WhenAny(serverExitTask, parentProcessExitTask);

            if (completedTask == parentProcessExitTask)
            {
                logger.LogInformation("Parent process {parentProcessId} exited, shutting down server", parentProcessId);
            }
        }
        else
        {
            await server.WaitForExitAsync();
        }
    }
    finally
    {
        // After the LSP server shutdown, report session wide telemetry
        RoslynLogger.ShutdownAndReportSessionTelemetry();

        // Server has exited, cancel our service broker service
        await serviceBrokerFactory.ShutdownAndWaitForCompletionAsync();
    }
}

static RootCommand CreateCommand()
{
    var debugOption = new Option<bool>("--debug")
    {
        Description = "Flag indicating if the debugger should be launched on startup.",
        Required = false,
        DefaultValueFactory = _ => false,
    };
    var brokeredServicePipeNameOption = new Option<string?>("--brokeredServicePipeName")

Review comment (suggestion):
`serverExitTask`/`parentProcessExitTask` are started and then only the winner of `Task.WhenAny` is checked, but neither task is awaited. If either task faults, the exception can go unobserved; additionally, when the parent-exit task wins the server is not explicitly stopped. Consider awaiting the completed task (to observe exceptions) and ensuring the process exits promptly/cleanly when the parent process ends (for example by initiating/forcing server shutdown before leaving this block).
```suggestion
                logger.LogInformation("Parent process {parentProcessId} exited, shutting down server", parentProcessId);
                await parentProcessExitTask;
            }
            else
            {
                await serverExitTask;
            }
```

Code after:
        Console.WriteLine(JsonSerializer.Serialize(new NamedPipeInformation(clientPipeName)));

        // Wait for connection from client
        await pipeServer.WaitForConnectionAsync(cancellationToken);

        server = new LanguageServerHost(pipeServer, pipeServer, exportProvider, loggerFactory, typeRefResolver);
    }

    server.Start();

    logger.LogInformation("Language server initialized");
    RoslynLog.Logger.Log(RoslynLog.FunctionId.VSCode_LanguageServer_Started, logLevel: RoslynLog.LogLevel.Information);

    try
    {
        if (serverConfiguration.ClientProcessId is int clientProcessId)
        {
            logger.LogInformation("Monitoring client process {clientProcessId} for exit", clientProcessId);
            var serverExitTask = server.WaitForExitAsync();
            var clientProcessExitTask = WaitForClientProcessExitAsync(clientProcessId, logger);
            var completedTask = await Task.WhenAny(serverExitTask, clientProcessExitTask);

            if (completedTask == clientProcessExitTask)
            {
                logger.LogInformation("Client process {clientProcessId} exited, shutting down server", clientProcessId);

                // With the client process exited, we cannot send logs or telemetry,
                // so kill the server process immediately to ensure we exit in a timely manner.
                Process.GetCurrentProcess().Kill();
            }

            // Await the task that completed to observe any exceptions.
            await completedTask;
        }
        else
        {
            await server.WaitForExitAsync();
        }
    }
    finally
    {
        // After the LSP server shutdown, report session wide telemetry
        RoslynLogger.ShutdownAndReportSessionTelemetry();

        // Server has exited, cancel our service broker service
        await serviceBrokerFactory.ShutdownAndWaitForCompletionAsync();
    }
}

static RootCommand CreateCommand()
{