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

:start sometimes gets called twice (ClojureScript) #112

Open
jwr opened this issue Nov 25, 2019 · 2 comments
Open

:start sometimes gets called twice (ClojureScript) #112

jwr opened this issue Nov 25, 2019 · 2 comments

Comments

@jwr
Copy link

jwr commented Nov 25, 2019

After a grueling multi-day trial-and-error debugging session I have finally confirmed that it is possible for the :start method to be called twice by mount in ClojureScript.

I suspected this for a long time, I even had an atom to guard and log cases of dual invocation in one of my files, but I always wrote it off as a temporary browser caching phenomenon, as I only noticed it in development, not in production bundle. However, recently it started happening in the production bundle as well.

Unfortunately, I can't provide a reproducible case. This seems to be an extremely elusive bug: it seems to depend on file sizes or file arrangement. Once the app is built, it will happen predictably every time, and recompiling the same code will reproduce the problem as well, but adding even a single println might stop it from happening. Then removing the println makes it happen again.

In my case, it happens in with a namespace that is used by lots of other namespaces. Race condition somewhere, perhaps?

I verified that mount/start is called only once.

I realize this isn't much to go on, but I think it's something worth knowing. Perhaps others can deduce how this is possible, perhaps safeguards can be put in place so that it doesn't happen. It can result in really hard-to-track problems.

@tolitius
Copy link
Owner

thanks for reporting this. from the mount side it is difficult to know the intention: i.e. "did you want to call mount/start twice", "did you call (mount/start a) and then (mount/start)", etc..

on a ClojureScript side things are always harder since "there are no threads, but there are threads" due to the way browsers handle the event loop and/or websockets, etc.

by itself calling (mount/start) twice won't hurt an application since mount would not start a state/component in case it is already started. If you observe the double start of a component, that would only mean that either mount's internal state was wiped, or, as you mentioned there could have been a race condition where an application called mount/start at "virtually the same" time and some components might have taken "long" time to load. (this is just a guess).

one thing that might help you is (mount/running-states) that returns a set of states that are running at the moment. in your start function, you can try verifying if your state is started by running this set against its name and ignore starting it if it is already started. This would not be a solution, but more of a "add some clarity / safety" exercise.

@jwr
Copy link
Author

jwr commented Dec 4, 2019

To clarify again: I am certain that mount/start is only called once.

In spite of this, at least in some namespaces, the :start method is sometimes called twice (exactly twice, never more).

This does sound like a race condition somewhere, especially because adding or removing a single println could change the behavior.

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

2 participants