Closed ylg closed 1 year ago
Hi @ylg Any updates on this?
I have encountered the same problem. Recently upgraded RayGun 2.25.4 -> 2.27.0 and now in some cases when the page is loaded for the first time the application freezes and gets into an infinity loop.
@vladyc9 Sorry, the workaround I mention was the best we ever came up with. Given Raygun's silence on the matter, we ended up with the only perfect solution being to shift our clients away from Raygun. That's still a work in progress, but the workaround works at least well enough that if end users are experiencing the issue on the couple apps still needing to be moved, it's not frequent enough to report (granted that's a terrible place for an app to be).
@ylg Got it, thanks for your reply !
Hello @ylg and @vladyc9
Thank you for bringing this to our attention,
I have been able to replicate this issue and am currently working on a fix.
I will keep you all posted with my progress
Hi @Hamish-taylor It's a really good news! We are waiting for the fix.
Please keep us updated. Thank you!
To give an update on my progress. I have opened a PR #505 with a fix that is currently in the process of being tested. We are hoping to release this by the end of this week or early next week. If you are curious (and for added visibility) here's a summary of what the issue was and how it was fixed.
We are assuming rg4js is loaded when document.readyState
is marked as complete
. However, this is not true, it's not loaded until after the load
event has fired. According to the document readyState spec the complete
state indicates that the load event is about to fire. This leaves a small gap between the document state being marked as complete and raygun4js being initialized. If a Raygun event (I.e. rg4js(...)) is processed in this gap we try to call rg4js but since it is not loaded the object is a reference to the function currently executing which causes an infinite recursive loop that will hang the application.
I have added a RaygunInitialised
variable onto the window that will be set to true once raygun4js has been fully initialized. The UMD module will wait for this variable instead of document.readyState === complete
. The result being if the code is executing in the gap it will not get its self caught in the loop.
@Hamish-taylor Thanks for the explanation, do you have an ETA on the fix being released?
We are hoping to do a full release of the package early next week. We are currently in the testing phase to ensure that no issues or bugs have been introduced. As a part of this I have added a beta version of the update to NPM (2.27.3-beta.0). If you have the time we would greatly appreciate your feedback on whether the update helps to solve the problems you have been encountering
Hello @ylg @vladyc9 @MarcEspiard I have just published version 2.28.0 of raygun4j to NPM which includes fixes for this issue!
Seemingly out of the blue, yesterday users of one iPadOS 15.5, home-screen-only PWA began reporting the app would fail completely to start up. Investigating, I found seemingly at random rg4js would take a path that leads to an infinite loop upon its first non-configuration call, e.g., "send", "setUser". If I strip away all the code making that first call, then the next "new" first call triggers it. When the app starts from scratch, i.e., after an iOS app quit, it is very likely to fail (maybe 9 out 10 attempts will fail). When the app starts from a forced reload, e.g., cmd-R from the debugger, it is very unlikely to fail (maybe 1 out 10 attempts will fail).
Oddly, nothing has changed in this app in a while. The affected app is a mobile Safari (iPadOS) only PWA that heavily uses React/Redux (with localForage). We've another iPadOS-only PWA with very similar code that does not present this. So my wild guess is this presentation is connected to IndexedDB state/content (and therefore
localforage.ready()
behavior).We can seemingly work-around this by moving rg4js setup outside and above the
localForage.ready()
call. There's actually no need for it to be inside the call, merely "that's how it's always been". However, given the sudden and random appearance of this, I'm not 100.0% comfortable moving it eliminates the problem as opposed to merely lowering the probability so that by pure luck we've not yet seen it recur in test.The below seems to work so far:
While this randomly/intermittently fails:
Note that none of the above rg4js calls appear in the stack of the infinite loop and all are successfully completed before whatever rg4js invocation does loop, e.g. "setUser". That is, moving these config calls inside/outside the
.ready()
callback does not change the order of rg4js calls. Of course, it likely does change the overall sequence of events outside of rg4js.It looks like the loop is in/around this line:
https://github.com/MindscapeHQ/raygun4js/blob/f003e45544e329264bb07378ac8b5eb0250752cf/src/umd.intro.js#L45
You'll see I've a breakpoint on the offending line. Every time the app starts without the infinite loop, that line is never executed. Every time the app starts with an infinite loop, that line is executed (and always appears in the loop stack).
For what it's worth, I think it's totally fine saying rg4js cannot be configured within localForage.ready() (or a similar non-root level and async handler). I'm less interested in a change in rg4js behavior than I am in knowing how to be certain we're avoiding the problem entirely and/or need to do more than merely moving the config to do so.
[Edit] To be clear, the entire app is gated by/invoked within that localForage.ready() handler after the rg4j calls, so there's nothing else running async with ready().