Skip to content

This apparently acyclic combination of Import-Module calls results in stack overflow #12039

@alx9r

Description

@alx9r

This came up after #12036 and #12014 while trying to implement the proposed solution for those issues. The solution to those issues will, ostensibly, involve liberal calls to Import-Module within modules during module loading to shadow the names of commands such that name resolution occurs in module and not global scope. In practice I have found that there are scenarios where such liberal use of Import-Module causes stack overflows. Some such stack overflows are the result of straightforward cyclic calls to Import-Module. This one is slightly different as it is apparently acyclic.

One module affected by this is (a later, internal version of) StructuredResource. The culprit seems to be these lines which validate that the DSC resource module imports without error. A DSC resource that requires StructuredResource is also tested by and therefore imported by StructuredResource. I suspect this is an unusual perhaps inadvisable use case, but I'd still like to understand what is happening so I can conclusively work around the stack overflow.

This leaves me with the following questions:

  1. Why isn't this acyclic? Why does this cause a stack overflow?
  2. Is there some other way to cross-import without stack overflow?

Referring to the repro below, here is what I would have expected to happen:

  1. p1 is called which results in imported module p then p1 is invoked
  2. p1 outputs p1 then imports module m into p1's scope
  3. import of module m includes a call to Import-Module p so module p is imported a second time, this time into module m's scope
  4. the second import of module p does not result in any more imports or calls and the whole stack unwinds (*)

(*) In (4) the call to Import-Module m is within the p1 scriptblock and so should not be invoked by the module import.

This is not, however, what happens. Stack overflow seems to occur after (3) but before (4) is reached.

Steps to reproduce

Create two well-formed modules m and p in $Env:PSModulePath:

# m.psm1
Write-Host 'import m'
Import-Module p
# p.psm1
Write-Host 'import p'
function p1 { Write-Host 'p1'; Import-Module m}

Invoke the following:

p1

Expected behavior

import p
p1
import m
import p

Actual behavior

import p
p1
import m
Stack overflow.

image

Environment data


Name                           Value
----                           -----
PSVersion                      7.0.0
PSEdition                      Core
GitCommitId                    7.0.0
OS                             Microsoft Windows 6.3.9600
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-BugIssue has been identified as a bug in the productResolution-No ActivityIssue has had no activity for 6 months or moreUp-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsWG-Cmdlets-Corecmdlets in the Microsoft.PowerShell.Core module

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions