-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
StopTheHostException should be made public to be dealt with gracefully #60600
Comments
@davidfowl - thoughts here? My assumption is that |
The EF CLI throws a starts up the host to read database configuration and then throws a StopTheHost exception to stop the host from doing anything else. Check for that expected exception so that it is not logged as a fatal error. See also dotnet/runtime#60600.
Any idea on what the proper way to handle this would be? my code is now: protected void CreateHost()
{
if (HostBuilder == null)
throw new InvalidOperationException(nameof(HostBuilder) + " was null");
try
{
Host = HostBuilder.Build();
// Release resources
HostBuilder = null;
}
catch (Exception e) when(e is not OperationCanceledException && e.GetType().Name != "StopTheHostException")
{
_logger?.LogCritical(e, "Caught exception whilst building Host");
throw;
}
} I'm running into this ex with a custom bootstrapper and ef core - would this be the proper way to handle this? |
@eerhardt we need to expose something basic for this scenario either an interface or the exception itself if we want to avoid code like above. The scenarios are pretty narrow though (avoiding the log for when migrations happen). We could at a minimum document the current behavior. |
This is extremely important. As long as you throw an exception, you can only expose that exception. This is clearly a design error, but fortunately the problem can be easily solved by simply exposing the exception. |
When do you see this exception happen in practice? Locally during development right when adding Migrations right? Narrow doesn't mean that its not important, but if there are more cases than we're aware of, that would be nice to know. |
@nanasi880 the HostFactoryResolver prefers the older patterns; I worked around this exception issue by just moving my IHostBuilder creation to a static Program.CreateHostBuilder for EF to find. runtime/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/HostFactoryResolver.cs Line 126 in 13024af
In my case this was a CLI tool using System.CommandLine.Hosting which kept dumping StopTheHostException to the console after the ef migration was successfully created, it's a bit off the beaten path. However I've been frustrated in the past by unhandleable internal exceptions, since this can escape the platform code maybe it should be public. |
Thanks reply. @davidfowl @jasonthorsness
This means that from the Program class (the Main method of the entry point, to be precise), without ever going through an instance method (perhaps even dynamic branching by if is not allowed?). Is it necessary to write code to use IHostBuilder? In that case, it may not be practical to use this, as I prefer to use a model where subcommands distribute multiple functions (e.g., only perform migrations) |
This seems to be a pretty common problem. I agree we should do something about it. At this point I think it would make the most sense to make the exception public. (We should probably give it a better name if we are going that route.) @davidfowl - would you be OK with that? I assume this pattern is here to stay and won't be replaced anytime soon, so exposing the exception shouldn't be a big issue. Or are there plans to replace/change the HostFactoryResolver? |
OK lets expose the exception. I'm sympathetic to the problems experienced here as well. |
Setting the API proposal in namespace Microsoft.Extensions.Hosting
{
public partial class StopTheHostException : Exception
{
public StopTheHostException() { }
protected StopTheHostException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public StopTheHostException(string? message) { }
public StopTheHostException(string? message, System.Exception? innerException) { }
}
} |
We renamed namespace Microsoft.Extensions.Hosting
{
[Serializable]
public sealed partial class HostAbortedException : Exception
{
public HostAbortedException() { }
private HostAbortedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
public HostAbortedException(string? message) { }
public HostAbortedException(string? message, System.Exception? innerException) { }
}
} |
Seems to be a small issue. I think I would have time for that. If you are interested in a community contribution, feel free to assign me. |
@deeprobin sure looking forward to your contribution |
@maryamariyan Thank you for waiting. I've been busy lately. The PR will be made this week. |
The proposal proposes a Was this an exception (if so, for what reason?)? |
Yes. To quote that document:
(Emphasis mine.) |
@bartonjs Thank you. Should we obsolete the private ctor? |
If that's being done for other Exception-derived types, then yes. If not, then no 😄. (I don't know off the top of my head, but that's the formula) |
@bartonjs I did a grep in the extension-packages
I only found Accordingly, there is no standard to follow. |
Description
In brief,
StopTheHostException
should be made public as it may need to be handled by framework users.This commit introduced
StopTheHostException
thrown out of, ultimately,HostBuilder.Build()
on, among other things, adding a migration to a EF/.NET Core 6.0 RC2 project.The exception itself seems to be expected, and is supposed to be caught by HostFactoryResolver.
However, that private, formally undocumented exception reaches my code which I believe is quite a common pattern:
The following output is produced on an attempt to add a migration:
Reproduction Steps
(1) Add try/catch similar to the above around
IHostBulder.Build()
in any .NET/EF Core 6.0 RC2 project,(2) Attempt to add a migration.
Expected behavior
StopTheHostException
needs to be public and documented, to be able to be gracefully re-thrown. Alternatively, it should never propagate out of the framework.Actual behavior
StopTheHostException
is private, undocumented, and reaches customer code.Regression?
Yes - introduced in .NET Core 6.
Known Workarounds
I fixed the issue with the following:
Normally, I would use
catch(StopTheHostException)
or similar but I can't becauseStopTheHostException
is private.Configuration
Any ASP.NET Core/EF project, and potentially other kinds of projects.
Other information
No response
The text was updated successfully, but these errors were encountered: