Skip to content
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

StackOverflowException occures when subscribeMethod throws an exception using dotnet core #150

Closed
srollinet opened this issue Nov 19, 2016 · 7 comments
Milestone

Comments

@srollinet
Copy link

srollinet commented Nov 19, 2016

When subscribeMethod throws an exception, I get a StackOverflowException caused by Newtonsoft.Json (I don't know if it is related to #136)

you can easily reproduce it with the following code, using version 1.10.2

        public static void Main(string[] args)
        {
            var client = BusClientFactory.CreateDefault();
            client.SubscribeAsync<BasicMessage>(async (msg, context) =>
            {
                throw new Exception("boom!");
            });
            client.PublishAsync(new BasicMessage());
        }

        public class BasicMessage
        {
        }
@pardahlman
Copy link
Owner

Your code looks a lot like this test for when a subscriber throws. Could you provide me with a stack trace?

Don't think this relates to #136, as that only occurs with message context that hold complex Funcs.

@srollinet
Copy link
Author

Unfortunately a StackOverflowException has no stack trace.

I can give you the top of the stack if it helps.
image

Then I have only calls to SerializeObject until the maximum number of stack frames supported is exceeded.

Here is the entire code:
TestRabbit.zip

@pardahlman
Copy link
Owner

@srollinet I tried to reproduce this when you reported it, without any success. It just struck me that I was running under 4.5.1 and furthermore I believe I know what the problem is.

RawRabbit executes all message handlers with an IErrorHandlingStrategy. The default strategy for exceptions in a subscribe message handler is to publish the message on an error exchange together with metadata, including the thrown exception.

Serialization of Exception in dotnet core is not supported, which is exactly what we're doinig here.

You can temporary mitigate the issue by implement your own error handler and override OnSubscriberExceptionAsync.

I'm open fora discussion as for what the best approach is here. I think it makes sense to get some information about the exception throw, when etc. Perhaps we should just use the MessageHandlerExceptionInformation here. @ritasker any thoughts? As a side note, should we include the serialized message or the raw Body prop from the delivery args?

@srollinet srollinet changed the title StackOverflowException occures when subscribeMethod throws an exception StackOverflowException occures when subscribeMethod throws an exception using dotnet core Nov 20, 2016
@srollinet
Copy link
Author

Sorry, I forgot to mention it was dotnet core. I changed the title.

I will try with with a custom error handler for now.

@pardahlman
Copy link
Owner

No worries, I'm glad you reported this so we can update it.

@ritasker
Copy link
Contributor

I have been able to replicate the issue.
I have also implemented a version of IMessageSerializer that uses ServiceStack.Text, see here. This does not throw a StackOverflowException.
You can reproduce the exception thrown by JSON.Net with the following code.

public static void Main(string[] args)
{
    try
    {
        throw new Exception("boom!");
    }
    catch (Exception ex)
    {
        var serializer = new JsonSerializer();
        string json;
        using (var sw = new StringWriter())
        {
            serializer.Serialize(sw, ex);
            json = sw.GetStringBuilder().ToString();
        }

        var msgBytes = Encoding.UTF8.GetBytes(json);
        Console.WriteLine(msgBytes);
    }
    Console.ReadLine();
}

It throws the following exception on the serializer.Serialize(sw, ex); line.

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'EntryPoint' with type 'System.Reflection.RuntimeMethodInfo'. Path 'TargetSite.Module.Assembly'.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Serialize(TextWriter textWriter, Object value)
   at ConsoleApplication.Program.Main(String[] args) in /Users/richard/Documents/SourceCode/RabbitException/Program.cs:line 34

I am not sure if this is related to issue https://github.com/dotnet/coreclr/issues/2715 or not.
Further investigation required.

@pardahlman
Copy link
Owner

Nice catch! I was under the impression that serialization of exception was not supported in .NET core. It will be interesting to see what you find. Nevertheless, It is not an option to change the default serializer from Json.Net to ServiceStack, so we need to look at other options.

pardahlman added a commit that referenced this issue Dec 19, 2016
@pardahlman pardahlman added this to the 1.10.3 milestone Dec 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants