Skip to content

dotnet-watch run fails to reload on Debian machines that do not have the procps package installed #27950

Closed
@MichaelSimons

Description

@MichaelSimons

Describe the bug

dotnet-watch has some undocumented native dependencies. Specifically it depends on the pgrep command which is not installed on a clean Debian machine. dotnet-watch run silently fails to reload when the dependency is not present.

To Reproduce

Copied from dotnet/dotnet-docker#2396

Requirements: Linux Docker environment and the .NET 5 CLI

  1. Create a new simple "Hello world" webapp
mkdir /tmp/test && cd /tmp/test
dotnet new web
  1. Run it with dotnet watch run and the code mounted in a container
docker run -it --rm --workdir /app -v ${PWD}/:/app mcr.microsoft.com/dotnet/sdk:5.0 dotnet watch run

You'll notice that when opening, altering and saving the ./Startup.cs file, the service isn't reloaded.

Further technical details

  1. The mcr.microsoft.com/dotnet/sdk:5.0 image in this scenario is based on Debian. Installing the procps package resolves the issue.
  2. This is what I found with a quick investigation.

https://github.com/dotnet/aspnetcore/blob/master/src/Tools/dotnet-watch/src/Internal/ProcessRunner.cs#L164

_process.KillTree();

https://github.com/dotnet/aspnetcore/blob/master/src/Shared/Process/ProcessExtensions.cs#L20

public static void KillTree(this Process process, TimeSpan timeout)
{
    var pid = process.Id;
    if (_isWindows)
    {
        ...
    }
    else
    {
        var children = new HashSet<int>();
        GetAllChildIdsUnix(pid, children, timeout);
        foreach (var childId in children)
        {
            KillProcessUnix(childId, timeout);
        }
        KillProcessUnix(pid, timeout);
    }
}

private static void GetAllChildIdsUnix(int parentId, ISet<int> children, TimeSpan timeout)
{
    try
    {
        RunProcessAndWaitForExit(
            "pgrep",
            $"-P {parentId}",
            timeout,
            out var stdout);

  1. In discussing this with @pranavkm, it seems plausible that the KillTree implementation could be replaced with System.Diagnostrics.Process.Kill(bool entireProcessTree). This would be desirable as it would remove this native dependency.
  2. This was discovered while investigating a 5.0 regression with the .NET SDK Docker image. The procps package was removed in 5.0 as part of an effort to reduce the image size in order to provide a better UX. The dependency dotnet-watch has was unknown to all parties involved.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-commandlinetoolsIncludes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPIbugThis issue describes a behavior which is not expected - a bug.feature-dotnetwatchThis issue is related to the dotnet-watch command-line tool (now external)

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions