Hey guys,

We're developing a GUI'd application with guice.

I recently discovered a horrifying and rather tragic behavior within our 
software, *once in a while* it will enter deadlock when running under a 
couple specific situations.

I've got this deadlock down to a contention between two resources:

   - The JavaFX thread --specifically, we've written a method called 
   runImmedlatelyOnFX. the source code can be found here 
   <https://gist.github.com/Groostav/2944cb86e87848399924>, but its 
   effectively draining the fx job queue.
   - A singleton's constructor.

The scenario is:

   1. Worker-Thread requests and instance of singleton-class B from guice.
   2. Guice acquires some kind of mutex to indicate that its constructing a 
   singleton, and calls the Class-B constructor on Worker-Thread.
   3. the JavaFX application thread requests an instance of singleton-class 
   B from guice. *It's blocked by guice pending the result from 
   Worker-Thread's Class-B-Construtor call*.
   4. The constructor for singleton-class B calls runImmediatelyOnFX. *It's 
   blocked until the JavaFX thread executes its enqueued job*

*and we have deadlock.*


So I don't think it will be too helpful to get into a deep discussion about 
our usage of JavaFX, but I'm wondering if anybody else has run into this 
problem, and if there's some miracle solution I'm not aware of.


The two things I can employ to mitigate/solve this problem:

   - There is one overt use case for this runImmediately business, and it 
   has to do with loading fxml documents (typically done in constructors). If 
   I make our UI code a little bit more flexible about when it actually gets 
   an instanced view tree (read: in a callback rather than in the ctor), we 
   can reduce the number of ctor's that block on runImmediately() quite 
   significantly.
   - I can use use Quantem's enterNestedEventLoop() 
   
<http://grepcode.com/file/repo1.maven.org/maven2/net.java.openjfx.backport/openjfx-78-backport/1.8.0-ea-b96.1/com/sun/javafx/tk/Toolkit.java#Toolkit.enterNestedEventLoop%28java.lang.Object%29>
 
   to give the appearance of running immediately on the javaFX thread without 
   actually blocking the javaFX thread. This will likely defeat the purpose of 
   the method for some use cases, so the old "enqueue the job and wait" 
   strategy will have to remain available for them, but it will likely be 
   sufficient for most of the callers. 
   

Is there something I'm missing? Is there some architectural master stroke 
somebody can fill me in on to deal with this problem quickly and easily?


One of the things I'm looking to do now is start failing integration tests 
when they notice the potential for this deadlock. My plan for this is to 
have SyncingUtilitles.runImmediatelyOnFXThread and guice singletons act 
like resource acquisitions, with each checking to see if the thread they're 
running on has already acquired the other. If they have, they would log 
some kind of warning that they may be entering deadlock. logging a warning 
will fail our cucumber performance tests and our ranorex UI automation 
tests, which should prevent us from pushing new code with these issues.


I haven't started writing that provision listener, is it technically 
possible?


Thanks for any help!


-Geoff

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-guice+unsubscr...@googlegroups.com.
To post to this group, send email to google-guice@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/google-guice/2b89be39-c127-45e0-871d-4e46b42812ae%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to