-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Discussion: should PowerShell implement assembly load contexts for module dependencies, and how? #12920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Nope. No way, no how. ALCs are a pretty advanced concept, and I very much doubt you could reliably code a module to work both in an isolated and the shared ALC. Letting users of a module turn that on or off on a whim is pretty much just going to break things, and not much else.
Yeah, sure, it may not be super useful for all modules, but it definitely could come in handy for some. Authors should be able to pick, 100%.
Feasible? Potentially. On the assumption that we do make it a feature, though, tooling and documentation will be necessary. Don't know enough to comment on the other bits, I think, I'll leave that to the cleverer cookies. 🙂 |
I definitely agree with this point. I just want to raise a counterpoint which is that trying to defuse a module dependency conflict is a user scenario. If only module authors get to decide, then they must do the due diligence on what other modules they might conflict with. When a user uses a module and it conflicts with something, there’s no switch they can try to get them out of a bind (like there is with OTOH perhaps that’s exactly as it should be. Users find a conflict and circle back to authors ask them to evaluate ALC loading. |
I feel like we've already had parts of this discussion elsewhere. Is there an issue I've forgotten about? |
#2083 was the big one. #5504 also looks related. This would be a fantastic tool to allow module developers to take on dependencies without worrying about breaking the environment. One thing I'd really like to see is an easy way to allow public types from the modules assembly to be resolvable by PowerShell, while still "hiding" the dependencies. Maintaining the ability to strongly type variables, use the Personally I would only want to see this surfaced as an option for the module author, definitely off by default. |
I updated the issue description with the above content, just to call out that we have an RFC about this that was withdrawn at the time. |
I'm not sure that I have a specific suggestion here, but wanted to provide some input about how we've hacked around these issues.
This is all terrible, and we'd absolutely welcome something better. On the other hand, we have been able to make it mostly work for our scenarios. While I agree that asking module authors to engage with and understand ALCs might not be a great idea, I also wouldn't want the PS runtime to impose some "standard" behavior that breaks scenarios that can be made to work now (albeit badly). I'm not sure how you differentiate the scenario where you're loading some module because you just want access to commands it exports and the scenario where you're loading it because you want the side effect of making types in the assemblies it loads to be made available to you (either directly or to another dependency you're going to load). At least I can't see how a default behavior would know which of these you're looking for unless you had some way to explicitly indicate that. That might not mean fully exposing the gory details of ALCs, but you'd need something. Making the 80% case easy and the 20% case impossible is worse than the 100% case being hard. |
For my most common use cases (Dumb example: I want to use Json 10 and Powershell uses Json 11+), if I could just specify assemblies or nuget packages in the manifest that would load into my module-specific ALC context but the rest of my module stays in the main context, I'd be happy. As long as I follow a couple rules:
Then I can make my modules more broadly compatible. A wider ability of Powershell to "auto-detect" this so that module authors don't have to even think about it would be great, but to at least get something out the door it's a good place to start. |
If you mean autodetection of whether those rules are followed, we could never do it safely because it's unfortunately undecidable given current APIs. Something like I don't mean that as a way of saying everything is impossible or shouldn't be done, more just want to establish that no strong solution exists for some of the problems we face here. |
I suggest to start at 7.2 milestone with most simple and obvious - add an experimental parameter to Import-Module cmdlet so that PowerShell users can load module dependencies in ALCs. This will open the way for broader experimentation and provide more specific and useful feedback. |
@iSazonov I'm not sure it makes sense as a |
@SeeminglyScience I agree, I think at this point just make some helpful cmdlets to load assemblies into an ALC for the module author without them needing to know C#. Something like |
Yeah that's the right direction for sure. I think even that has it's obstacles though, especially around dependency resolution. I know PSES had to register some custom assembly resolution handlers, not sure how typical that is. |
Our goal is to get working modules despite the presence of conflicting assembly versions. Simply loading an assembly using Add-Type, or say it should be the concern of the module author, won't get us a step further. |
@iSazonov agreed, that's the ideal, I'm just saying baby steps to at least get a friendly ALC context for a module developer would be great for 7.2 vs. a more ambitious full module resolution and all the edge cases that would probably push it to 7.3 or more. |
To clarify, I'm not saying it should be, I'm saying it has to be because of how they work. It's not the perfect solution it may have seemed like originally, it's incredibly finicky and needs to be actively designed around. |
This is why we need the experimental parameter to load two modules and do live testing. |
I'm not saying it's unpredictable, I'm saying it needs to be explicitly designed around. |
While this is being worked out, what is the direction to typical PowerShell users who are unable to import two modules into the same session. In my case I am unable to import powershell-yaml and platyPS into the same session.
Is the response simply that you can not use these two modules together? Or is the expectation that the user should log an issue with one of the module owners? Is this something that would be reasonable to expect a fix for from the module owner? |
@Stewartarmbrecht the current workaround I use is to " The only other option in terms of module author support would be to expand Powershell Standard to include some of the most common libraries, so that module authors use the same assembly versions and don't conflict. This is fraught with issues however especially if a module author requires a newer version of a module. |
Thanks @JustinGrote I'll work on running PlatyPS using Start-Job. |
Besides an impact on memory, what are the drawbacks of having every PS module load its dependencies into it's own ALC by default? This is how npm works and it makes it easy to depend on a lot of external packages. |
@Jeff-Lewis the biggest one is module owner discipline. If you return an ALC type to the user, and the type is already loaded, you get the very confusing "cannot cast MyType to type MyType" error message. There would have to be extensive sanity checking here to make this usable to the "common" module author who's not a guru. |
I don't really have any suggestions. But as a script-based module author, I'd just like to request that whatever solution eventually comes will work with script-based modules in addition to binary modules. There doesn't seem to be any good workarounds at the moment that don't involve getting into esoteric (to me) .NET compilation stuff. My only option seems to be trying to match dependency versions with other modules that my users report conflicts with. |
@rmbolger Are you basically expecting |
I don't use My module also works on both PS 5.1 and 6+. So I'd hope the manifest changes would remain backwards compatible which probably means they'd have to live in the |
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you. |
2 similar comments
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you. |
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you. |
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes. |
Uh oh!
There was an error while loading. Please reload this page.
.NET Core 2 introduced the concept of the AssemblyLoadContext.
This offers the possibility of preventing assembly dependency conflicts between modules, and even the possibility of unloading assemblies.
This has been successfully implemented in at least one PowerShell module in the wild. There's a blog post detailing how to do this here.
However, the question remains as to whether PowerShell should attempt to provide this functionality itself.
While it may sound like it definitely should, there are a number of subtle considerations, and it may be that PowerShell won't be able to get them right for all modules, making module loading more complex and error prone.
Some things to consider:
Note: An RFC about this topic that was withdrawn can be found here: https://github.com/PowerShell/PowerShell-RFC/blob/master/X-Withdrawn/RFC0043-Loading-Module-Into-Isolated-AssemblyLoadContext.md
The biggest challenge is the type identity issue. The module dependency is another challenge -- how to handle a required module? Today, the required module is loaded once and shared by multiple modules that depend on it.
Some other places where ALCs have been discussed:
The text was updated successfully, but these errors were encountered: