rebus-org / Rebus.AzureServiceBus

:bus: Azure Service Bus transport for Rebus
https://mookid.dk/category/rebus
Other
33 stars 20 forks source link

StackOverflow when starting bus with .NET Framework 4.8 web application #97

Closed MortenChristiansen closed 11 months ago

MortenChristiansen commented 11 months ago

I'm having a bit of trouble getting Rebus to work with Azure Service Bus in full framework applications. I have created a minimal .NET Framework 4.8 web application and when I start the bus I get a stack overflow exception.

Repro: https://github.com/MortenChristiansen/Rebus-Full-Framework-Repro You can add a user secrets xml or edit the app settings directly for setting up the ConnectionString and TenantId.

The stack trace seems to hint that Rebus is trying to create a Queue:

Rebus.AzureServiceBus.dll!Rebus.Internals.AsyncHelpers.CustomSynchronizationContext.Run.AnonymousMethod__7_0(object _)  Unknown
[Resuming Async Method] 
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()    Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.OutputAsyncCausalityEvents.AnonymousMethod__0() Unknown
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.OutputWaitEtwEvents.AnonymousMethod__0()   Unknown
mscorlib.dll!System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action action, bool allowInlining, ref System.Threading.Tasks.Task currentTask)    Unknown
mscorlib.dll!System.Threading.Tasks.Task.FinishContinuations()  Unknown
mscorlib.dll!System.Threading.Tasks.Task.Finish(bool bUserDelegateExecuted) Unknown
mscorlib.dll!System.Threading.Tasks.Task<System.Threading.Tasks.VoidTaskResult>.TrySetException(object exceptionObject) Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.SetException(System.Exception exception) Unknown
[Completed] Rebus.AzureServiceBus.dll!Rebus.AzureServiceBus.AzureServiceBusTransport.InnerCreateQueue.AnonymousMethod__1()  Unknown

...

Azure.Core.dll!Azure.Core.Pipeline.HttpWebRequestTransport.ProcessInternal(Azure.Core.HttpMessage message, bool async)  Unknown
[Resuming Async Method] 
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()    Unknown
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.OutputAsyncCausalityEvents.AnonymousMethod__0() Unknown
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.OutputWaitEtwEvents.AnonymousMethod__0()   Unknown
mscorlib.dll!System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action action, bool allowInlining, ref System.Threading.Tasks.Task currentTask)    Unknown
mscorlib.dll!System.Threading.Tasks.Task.FinishContinuations()  Unknown
mscorlib.dll!System.Threading.Tasks.Task.Finish(bool bUserDelegateExecuted) Unknown
mscorlib.dll!System.Threading.Tasks.Task<System.__Canon>.TrySetException(object exceptionObject)    Unknown
mscorlib.dll!System.Threading.Tasks.UnwrapPromise<System.Net.WebResponse>.TrySetFromTask(System.Threading.Tasks.Task task, bool lookForOce) Unknown
mscorlib.dll!System.Threading.Tasks.UnwrapPromise<System.Net.WebResponse>.Invoke(System.Threading.Tasks.Task completingTask)    Unknown
mscorlib.dll!System.Threading.Tasks.Task.FinishContinuations()  Unknown
mscorlib.dll!System.Threading.Tasks.Task.Finish(bool bUserDelegateExecuted) Unknown
mscorlib.dll!System.Threading.Tasks.Task<System.__Canon>.TrySetException(object exceptionObject)    Unknown
mscorlib.dll!System.Threading.Tasks.TaskFactory<System.__Canon>.FromAsyncCoreLogic(System.IAsyncResult iar, System.Func<System.IAsyncResult, System.__Canon> endFunction, System.Action<System.IAsyncResult> endAction, System.Threading.Tasks.Task<System.__Canon> promise, bool requiresSynchronization)  Unknown
mscorlib.dll!System.Threading.Tasks.TaskFactory<System.Net.WebResponse>.FromAsyncImpl.AnonymousMethod__0(System.IAsyncResult iar)   Unknown
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
System.dll!System.Net.ContextAwareResult.Complete(System.IntPtr userToken)  Unknown
System.dll!System.Net.LazyAsyncResult.ProtectedInvokeCallback(object result, System.IntPtr userToken)   Unknown
System.dll!System.Net.HttpWebRequest.SetResponse(System.Exception E)    Unknown
System.dll!System.Net.ConnectionReturnResult.SetResponses(System.Net.ConnectionReturnResult returnResult)   Unknown
System.dll!System.Net.Connection.CompleteConnectionWrapper(object request, object state)    Unknown
System.dll!System.Net.PooledStream.ConnectionCallback(object owningObject, System.Exception e, System.Net.Sockets.Socket socket, System.Net.IPAddress address)  Unknown
System.dll!System.Net.ServicePoint.ConnectSocketCallback(System.IAsyncResult asyncResult)   Unknown
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) Unknown
System.dll!System.Net.ContextAwareResult.Complete(System.IntPtr userToken)  Unknown
System.dll!System.Net.LazyAsyncResult.ProtectedInvokeCallback(object result, System.IntPtr userToken)   Unknown
System.dll!System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped)  Unknown
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) Unknown
[Native to Managed Transition]  
mookid8000 commented 11 months ago

Hmm I can't seem to "reproduce the reproduction" 😅

I configured the connection string and tenant IT, and I verified in the debugger that they were picked up, but I then got this error when I press F5: image

I then added the System.Text.Json NuGet to Repro, and then it started without any problems.

Btw: Your ConfigureRebus method will create and start a bus instance and immediately shut it down again, because the handler activator is disposed. You should keep either the handler activator or the bus instance around for the entire duration of your application's lifetime, and then dispose them when shutting down.

Btw2: Isn't it possible for you to use .NET? Rebus has really nice hosting integration (via Rebus.ServiceProvider), which makes it possible for you to configure Rebus by going

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, queueName))
);

and then have it handle proper start/stop without any additional effort on your part. 🙂

MortenChristiansen commented 11 months ago

Hmm, it must be something specific to my environment then. Lovely 😕. I'll see if I can get a colleague to repro it tomorrow.

Regarding the other comments, did you mean to ask if I could use .NET Core? Because I am using .NET. I'm adding queue functionality to existing applications which must be able to run on .NET Framework 4.8, so I can't use the services extension method. I was actually unable to find any documentation on how to best use Rebus with a classical ASP.NET application which is why you see me fumbling my way towards a solution 😄. It does not help that I haven't worked with full framework web apps for a long while.

mookid8000 commented 11 months ago

Yes, I meant ".NET Core" even though it's called ".NET" nowadays 😉 (since .NET 5 I believe)

And fair enough, not everyone can have the luxury of working on new stuff all the time.

It's entirely possible to host Rebus inside a classical ASP.NET application, but please be aware that if it's hosted in IIS, then you probably want to configure it to be "always on", unless you only want to process messages while the web app is loaded.

To host it in classic ASP.NET, you'll simply need to figure out how to properly dispose the bus when the web app is closed down – that's the only thing you're missing from the repro code you showed me.

Let me know if you need anything more specific 🙂