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

Observable.Generate & Low TimeSpan throws Exception #27

Closed
mattpodwysocki opened this issue Oct 13, 2014 · 2 comments
Closed

Observable.Generate & Low TimeSpan throws Exception #27

mattpodwysocki opened this issue Oct 13, 2014 · 2 comments
Labels

Comments

@mattpodwysocki
Copy link
Contributor

Copied from https://rx.codeplex.com/workitem/77

When TimeSpan.Zero or TimeSpan with a value < 1ms is passed to Observable.Generate a System.StackOverflowException is thrown. Looks like there is an infinite loop or a recursion happening.

@bartdesmet
Copy link
Collaborator

The only reason I can envision for this to happen is if a) System.Reactive.PlatformServices.dll is not deployed alongside your application and b) you're running on a platform where the TPL does not have proper support for stack probing to avoid stack overflows.

What happens here is that System.Reactive.Core uses the Concurrency Abstraction Layer (CAL) to run a timer for the TimeSpan obtained from the Generate time selector function. If you're using the Portable Library version of Rx, the default implementation uses Task.Delay to run a timer. That is, unless the Platform Enlightenment Provider succeeds to load System.Reactive.PlatformServices.dll for your specific target platform, i.e. from the binaries deployed alongside your application. If such a custom set of enlightenments is retrieved, behavior could be upgraded to use System.Threading.Timer instead.

However, if the default behavior is used, Task.Delay for anything less than a millisecond will return a task that completes immediately. The timer appends a continuation with the ExecuteSynchronously flag set to the delayed task. In case the task completes immediately, that causes the continuation to run inline, hence growing the stack. For all modern desktop platforms, the TPL has functionality to use a "stack guard" to check whether there's enough stack space left. If not, it will not honor the request to execute synchronously and will jump to a different threadpool thread instead. If stack probing isn't present (e.g. because there's no P/Invoke to the underlying Win32 APIs, something being addressed in Core CLR by adding runtime support to do the checks), there may be an overflow. I need to double-check which platforms could be affected by this.

If you could provide more information on the platform used and the application configuration (i.e. whether you're using the Portable Library build with or without a PlatformServices copy alongside of it), that'd be helpful to get to the root cause.

@bartdesmet
Copy link
Collaborator

We checked a couple of different configurations but couldn't reproduce the issue. Closing it for now. Feel free to reopen if you got more information that'd help to repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants