none
Process is terminated due to StackOverflowException

    Soru

  • Hi!

    Code below causes StackOverflowException:

    var xs = new Subject<int>();
    var ys = new Subject<Unit>();
    
    using (xs.Buffer(() => ys).Subscribe(_ => { }))
    {
        ys.OnCompleted();    
    }

    Rx version — 1.0.10621.0.

    Is this a bug in Rx?

    12 Mart 2012 Pazartesi 10:57

Yanıtlar

  • Thanks for taking the time to report this issue.

    I've investigated the problem and the behavior you're seeing can be explained by the use of a Subject<T> for the duration selector "ys". Subjects have a sticky terminal message behavior, meaning they remember when you post OnError or OnCompleted to them, so that subsequent subscribers will observe there's no values to expect anymore.

    In this particular case, when "ys" sends out an OnCompleted call to the code in Buffer, we do a few things:

    • The duration is finished, hence the current buffer is finished, so we send it out. In this case, any buffer over xs - an infinite but empty stream - will be an empty list, so you'll see that come out in the Subscribe handler.
    • Because the duration is finished, we will call () => ys again, to obtain the next buffer's duration sequence. However, in this case the same subject is used, which is already completed, so we end up in an infinite recursion.

    We can fix the stack overflow behavior, but the bigger question is what you're trying to do. Maybe this overload of Buffer doesn't do what you think it would, or the behavior of Subject is not what you expect it to be.


    using (Microsoft.Sql.Cloud.DataProgrammability.Rx) { Signature.Emit("Bart De Smet"); }

    • Yanıt Olarak İşaretleyen epetrukhin 19 Mart 2012 Pazartesi 12:30
    18 Mart 2012 Pazar 21:54

Tüm Yanıtlar

  • Thanks for taking the time to report this issue.

    I've investigated the problem and the behavior you're seeing can be explained by the use of a Subject<T> for the duration selector "ys". Subjects have a sticky terminal message behavior, meaning they remember when you post OnError or OnCompleted to them, so that subsequent subscribers will observe there's no values to expect anymore.

    In this particular case, when "ys" sends out an OnCompleted call to the code in Buffer, we do a few things:

    • The duration is finished, hence the current buffer is finished, so we send it out. In this case, any buffer over xs - an infinite but empty stream - will be an empty list, so you'll see that come out in the Subscribe handler.
    • Because the duration is finished, we will call () => ys again, to obtain the next buffer's duration sequence. However, in this case the same subject is used, which is already completed, so we end up in an infinite recursion.

    We can fix the stack overflow behavior, but the bigger question is what you're trying to do. Maybe this overload of Buffer doesn't do what you think it would, or the behavior of Subject is not what you expect it to be.


    using (Microsoft.Sql.Cloud.DataProgrammability.Rx) { Signature.Emit("Bart De Smet"); }

    • Yanıt Olarak İşaretleyen epetrukhin 19 Mart 2012 Pazartesi 12:30
    18 Mart 2012 Pazar 21:54
  • Thank you for explanation, Bart!

    Code above is reduced example only and, of course, it is incorrect. I was confused by exception type (StackOverflowException), expecting somethig like ObjectDisposedException or InvalidOperationException.
    19 Mart 2012 Pazartesi 12:30