Sdk: dotnet migrate fails on Linux if app directory is directly under a folder with a cyclic symlink

Created on 3 Feb 2017  路  7Comments  路  Source: dotnet/sdk

dotnet migrate fails on Linux if the app directory is directly under root (e.g. /app). It's easy to repro with docker containers, but it should also repro on the host OS.

It repros when using microsoft/dotnet-nightly:1.1.0-sdk-msbuild-rc4 or later. It works fine when using microsoft/dotnet:1.1.0-sdk-msbuild-rc3.

It also works fine if the app directory is two levels below root (e.g. /src/app).

Steps to reproduce

mkdir ~/new

docker run -it --rm -v ~/new:/new microsoft/dotnet:1.1.0-sdk-projectjson
cd new
dotnet new
exit

docker run -it --rm -v ~/new:/new microsoft/dotnet-nightly:1.1.0-sdk-msbuild-rc4
cd new
dotnet migrate

Expected behavior

App is migrated from project.json to MSBuild.

Actual behavior

dotnet migrate will either hang or throw the following exception:

root@08dd3e787323:/new# dotnet migrate
Migration failed.

Unhandled Exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/root/proc/7/fd/78'.
   at System.IO.UnixFileSystem.FileSystemEnumerable`1.OpenDirectory(String fullPath)
   at System.IO.UnixFileSystem.FileSystemEnumerable`1.<Enumerate>d__11.MoveNext()
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source, Int32& length)
   at System.IO.DirectoryInfo.InternalGetDirectories(String searchPattern, SearchOption searchOption)
   at System.IO.DirectoryInfo.GetDirectories(String searchPattern, SearchOption searchOption)
   at Microsoft.DotNet.ProjectJsonMigration.ProjectDependencyFinder.GetPotentialProjects(IEnumerable`1 searchPaths)
   at Microsoft.DotNet.ProjectJsonMigration.ProjectDependencyFinder.FindPossibleProjectDependencies(SlnFile slnFile, String projectJsonFilePath)
   at Microsoft.DotNet.ProjectJsonMigration.ProjectDependencyFinder.ResolveDirectProjectDependenciesForFramework(Project project, NuGetFramework framework, IEnumerable`1 preResolvedProjects, SlnFile solutionFile)
   at Microsoft.DotNet.ProjectJsonMigration.ProjectDependencyFinder.ResolveAllProjectDependenciesForFramework(ProjectDependency projectToResolve, NuGetFramework framework, IEnumerable`1 preResolvedProjects, SlnFile solutionFile)
   at Microsoft.DotNet.ProjectJsonMigration.Rules.MigrateProjectDependenciesRule.MigrateProjectJsonProjectDependency(Project project, NuGetFramework framework, HashSet`1 migratedXProjDependencyNames, SlnFile solutionFile, ProjectRootElement outputMSBuildProject)
   at Microsoft.DotNet.ProjectJsonMigration.Rules.MigrateProjectDependenciesRule.MigrateProjectJsonProjectDependencies(IEnumerable`1 projectContexts, HashSet`1 migratedXProjDependencyNames, SlnFile solutionFile, ProjectRootElement outputMSBuildProject)
   at Microsoft.DotNet.ProjectJsonMigration.Rules.MigrateProjectDependenciesRule.Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
   at Microsoft.DotNet.ProjectJsonMigration.DefaultMigrationRuleSet.Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
   at Microsoft.DotNet.ProjectJsonMigration.ProjectMigrator.MigrateProject(MigrationSettings migrationSettings)
   at Microsoft.DotNet.ProjectJsonMigration.ProjectMigrator.Migrate(MigrationSettings rootSettings, Boolean skipProjectReferences)

   at Microsoft.DotNet.Tools.Migrate.MigrateCommand.Execute()
   at Microsoft.DotNet.Tools.Migrate.MigrateCommand.<>c__DisplayClass35_0.<Run>b__0()
   at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args)
   at Microsoft.DotNet.Tools.Migrate.MigrateCommand.Run(String[] args)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, ITelemetry telemetryClient)
   at Microsoft.DotNet.Cli.Program.Main(String[] args)
Aborted (core dumped)

Environment data

dotnet --info output:

.NET Command Line Tools (1.0.0-rc4-004757)

Product Information:
 Version:            1.0.0-rc4-004757
 Commit SHA-1 hash:  f69f0ed266

Runtime Environment:
 OS Name:     debian
 OS Version:  8
 OS Platform: Linux
 RID:         debian.8-x64
 Base Path:   /usr/share/dotnet/sdk/1.0.0-rc4-004757

Most helpful comment

Thanks, that worked. I will update this issue with the correct root cause: dotnet migrate fails if the app directory is at the root. This is a fairly common pattern in docker containers (e.g. see the instructions at https://hub.docker.com/r/microsoft/dotnet/).

All 7 comments

It seems like you have a cyclic symlink somewhere. This is an issue called out at the GetDirectories API.

The host machine is a VM using the Azure image of Ubuntu 16.04 LTS, and docker was installed per the instructions at https://docs.docker.com/engine/installation/linux/ubuntu/. If there is a cyclic symlink, it's something that exists by default, so I think this scenario needs to work on this environment.

The cycle at /proc/[pid]/root/proc/[pid]/root/... appears to be by design:

  /proc/[pid]/root
              UNIX  and  Linux  support  the idea of a per-process root of the
              filesystem, set by the chroot(2) system call.  This  file  is  a
              symbolic  link  that points to the process's root directory, and
              behaves in the same way as exe, and fd/*.

http://manpages.ubuntu.com/manpages/xenial/man5/proc.5.html

I tried to repro on another VM which should have been identical. However, on this VM when I run dotnet migrate inside the docker container, rather than crash it just hangs.

Ok, I understand why this happens. This happens because you created your new project at the root of the docker machine. If you create something like src/new and then put your project there, it will work.

Migration looks at the parent folder you are migration migration at, in this case / so that it can find dependencies for your project, which is why we are hitting this issue.

We had to add the GetDirectories call with SearchOptions.AllDirectories so that we could actually find dependencies for a project that were deeper on the folder structure than the project itself.

Can you try the work around I suggested?

Thanks, that worked. I will update this issue with the correct root cause: dotnet migrate fails if the app directory is at the root. This is a fairly common pattern in docker containers (e.g. see the instructions at https://hub.docker.com/r/microsoft/dotnet/).

This issue was moved to dotnet/cli-migrate#27

Was this page helpful?
0 / 5 - 0 ratings

Related issues

clairernovotny picture clairernovotny  路  3Comments

natemcmaster picture natemcmaster  路  3Comments

thomaslevesque picture thomaslevesque  路  3Comments

gkhanna79 picture gkhanna79  路  3Comments

billwert picture billwert  路  3Comments