Re: JavaFX Application Thread is recursively re-entrant into Eventhandler handle() method under some circumstances

2018-09-09 Thread javafx
I am reading your stack trace but I defintely never mentioned the 
double invocation to handle that I see there are evidencing anything. 
The issue is the value of debugCounter at a two certain moments in the 
application - in the two calls to showDebugInformation. 


Although the proof that I am right is contained in the value 
debugCounter in the method showDebugInformation in the current program, 
if you go to the link in my previous post and download  and run the 
Complex version of this, you can more easily see the departure of the 
JavaApplicationThread from the instance of handle which is on the stack 
- and at a method which is not handle (as it is in this one) followed 
by  it's recursive re-entry to handle , completion of that 
recursive-handle's execution and re-entry and then completion into the 
previous invocation of handle. It's is completely obvious in the output 
of that Applcation. 


That application also throws the ConcurrentModificationException which 
is no way an artifact or misreading of a stacktrace. 


However, what is at issue in this program is the value of debugCounter 
in showDebugInformation.


Cheers. 
 
On Sunday, September 9, 2018 at 4:04 PM, John Hendrikx 
 wrote:

 

I see nothing special in the stack trace.

When you remove the component, a new MouseEvent *must* trigger
(MouseEvent.EXITED) as it always needs to match with 
MouseEvent.ENTERED.


So, the call to 'remove' triggers a new event, which gets handled by 
the

same handler.  It is indeed entered recursively, but in a normal
fashion.  This has nothing to do with another thread or compiler 
bugs.


Don't be confused by the double "handle" lines in the stacktrace. 
 This

happens when methods are overriden (the line number is 1).

There are two relevant lines in this trace:

   LabelEventHandler.handle(LabelEventHandler.java:95)

...where Remove is called, which triggers the recursive call later 
on:


   LabelEventHandler.handle(LabelEventHandler.java:88)

... for the MouseEvent.EXITED event.

The full stack trace is this:

at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:88)
at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:1)
at
javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at
javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at
javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at
javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at 
javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)

at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at 
javafx.base/com.sun.javafx.event.EventQueue.fire(EventQueue.java:48)

at
javafx.graphics/javafx.scene.Scene$MouseHandler.handleNodeRemoval(Scene.java:3717)
at
javafx.graphics/javafx.scene.Scene$MouseHandler.access$7800(Scene.java:3604)
at 
javafx.graphics/javafx.scene.Scene.generateMouseExited(Scene.java:3601)
at 
javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:613)

at
javafx.base/com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:329)
at
javafx.base/com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:221)
at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:95)
at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:1)
at
javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)

(... rest cut off as it is not needed ... )

--John

On 09/09/2018 19:05, jav...@use.startmail.com wrote:

Hi All,
I spent some time refactoring the program which displays this bug. 
It's
now small enough to share the source in an email, but it is very 
very
dense and the proof of bug, one  specific line to standard I/O, 
requires
the source code to be read and understood in order to see the bug. 
As I
said previously, more comprehensible and user-friendly versions of 
this

program are  available at . The javadoc is more copious, the bug is
manifested as an exception and the side effect of the bug are more
consequential.

This brief version cnosists of just two classes. H

Re: JavaFX Application Thread is recursively re-entrant into Eventhandler handle() method under some circumstances

2018-09-09 Thread javafx
I did not say it was another Thread. In fact, I said it was the Java 
Application Thread itself- being recursively re-entrant.


Specifically, at the time the MOUSE_EXITED_TARGET event is generated, 
the Java Application Thread has a choice- continue proocessing the 
EventHandler#handle method which it is in, or respond to 
the MOUSE_EXITED_TARGET event which was just generated. Suprisingly, it 
does the second , completes that call to handle, then the stack pops 
and it nfinishes the previous invocation of handle. It's not about 
another Thread.



I don't   refer to the stack trace as proof   that the thread is 
reentrant. I do say the contrapositve of that, which is, if the thread 
trace didn't show the bug  then the bug  wouldn't  exist. But I don't 
assert the stack trace as a proof.


The proof is  the proof  I gave in the javadoc, and that is the value 
of one the static int debugCounter acheives in the debug statements can 
only be explained if  recursive re-entrancy has cocurred, which  is 
true. You need to address this. 


Also, this is merely the most barebones implementation which reveals 
this bug. This is why I didn't want to post it, because you have to 
work out what cannot be the case before evaluating the argument. What 
cannot be the case is  debugCounter cannot have value 1 in the debug 
output method. 


The link provides a more consequential /  more easily understood bug / 
less dismissable bug- a ConcurrentModificationException  against a Set 
which the EventHandler is iterating through. That CME happens not 
because two threads are operating on the Set but because one thread , 
the JAva Application Thread is modifying the Set while it is also 
iterating through it. 


 


 
On Sunday, September 9, 2018 at 4:04 PM, John Hendrikx 
 wrote:

 

I see nothing special in the stack trace.

When you remove the component, a new MouseEvent *must* trigger
(MouseEvent.EXITED) as it always needs to match with 
MouseEvent.ENTERED.


So, the call to 'remove' triggers a new event, which gets handled by 
the

same handler.  It is indeed entered recursively, but in a normal
fashion.  This has nothing to do with another thread or compiler 
bugs.


Don't be confused by the double "handle" lines in the stacktrace. 
 This

happens when methods are overriden (the line number is 1).

There are two relevant lines in this trace:

   LabelEventHandler.handle(LabelEventHandler.java:95)

...where Remove is called, which triggers the recursive call later 
on:


   LabelEventHandler.handle(LabelEventHandler.java:88)

... for the MouseEvent.EXITED event.

The full stack trace is this:

at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:88)
at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:1)
at
javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at
javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at
javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at
javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at 
javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)

at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at 
javafx.base/com.sun.javafx.event.EventQueue.fire(EventQueue.java:48)

at
javafx.graphics/javafx.scene.Scene$MouseHandler.handleNodeRemoval(Scene.java:3717)
at
javafx.graphics/javafx.scene.Scene$MouseHandler.access$7800(Scene.java:3604)
at 
javafx.graphics/javafx.scene.Scene.generateMouseExited(Scene.java:3601)
at 
javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:613)

at
javafx.base/com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:329)
at
javafx.base/com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:221)
at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:95)
at
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:1)
at
javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)

(... rest cut off as it is not needed ... )

--John

On 09/09/2018 19:05, jav...@use.startmail.com wrote:


Re: JavaFX Application Thread is recursively re-entrant into Eventhandler handle() method under some circumstances

2018-09-09 Thread John Hendrikx

I see nothing special in the stack trace.

When you remove the component, a new MouseEvent *must* trigger 
(MouseEvent.EXITED) as it always needs to match with MouseEvent.ENTERED.


So, the call to 'remove' triggers a new event, which gets handled by the 
same handler.  It is indeed entered recursively, but in a normal 
fashion.  This has nothing to do with another thread or compiler bugs.


Don't be confused by the double "handle" lines in the stacktrace.  This 
happens when methods are overriden (the line number is 1).


There are two relevant lines in this trace:

   LabelEventHandler.handle(LabelEventHandler.java:95)

...where Remove is called, which triggers the recursive call later on:

   LabelEventHandler.handle(LabelEventHandler.java:88)

... for the MouseEvent.EXITED event.

The full stack trace is this:

	at 
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:88)
	at 
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:1)
	at 
javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at 
javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at 
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at 
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at 
javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at 
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at 
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at 
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at 
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at 
javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)

at 
javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.base/com.sun.javafx.event.EventQueue.fire(EventQueue.java:48)
	at 
javafx.graphics/javafx.scene.Scene$MouseHandler.handleNodeRemoval(Scene.java:3717)
	at 
javafx.graphics/javafx.scene.Scene$MouseHandler.access$7800(Scene.java:3604)

at 
javafx.graphics/javafx.scene.Scene.generateMouseExited(Scene.java:3601)
at 
javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:613)
	at 
javafx.base/com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:329)
	at 
javafx.base/com.sun.javafx.collections.VetoableListDecorator.remove(VetoableListDecorator.java:221)
	at 
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:95)
	at 
bareBonesJavaFXBugExample.LabelEventHandler.handle(LabelEventHandler.java:1)
	at 
javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)


(... rest cut off as it is not needed ... )

--John

On 09/09/2018 19:05, jav...@use.startmail.com wrote:

Hi All,
I spent some time refactoring the program which displays this bug. It's
now small enough to share the source in an email, but it is very very
dense and the proof of bug, one  specific line to standard I/O, requires
the source code to be read and understood in order to see the bug. As I
said previously, more comprehensible and user-friendly versions of this
program are  available at . The javadoc is more copious, the bug is
manifested as an exception and the side effect of the bug are more
consequential.

This brief version cnosists of just two classes. Here is the JavaFX
Application class:

***

package bareBonesJavaFXBugExample;


import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;



/**
 * An {@link Application} with one {@link Pane} containing one {@link
Label}. The {@link Label} has a single {@link
javafx.event.EventHandler}, {@link LabelEventHandler} which processes
all {@link MouseEvent}s the {@link Label} receives.
 * 
 * To trigger the bug, run the application, then spend a second mouse
over the little label in the upper left hand corner of the scrren. You
will see output to standard I/O. Then, click the label, which will then
disppear. Check the I/O for Strings ending in debugCounter is 1. 
 * What that String means and how it proves that the JavaFX Application
Thread has become reentrant is explained in the javadoc of {@link
LabelEventHandler}.
 */
public class JavaFXAnomalyBareBonesApplication extends Application
{
public void start(Stage primaryStage)
 

Re: JavaFX Application Thread is recursively re-entrant into Eventhandler handle() method under some circumstances

2018-09-09 Thread javafx

Hi All,
I spent some time refactoring the program which displays this bug. It's 
now small enough to share the source in an email, but it is very very 
dense and the proof of bug, one  specific line to standard I/O, 
requires the source code to be read and understood in order to see the 
bug. As I said previously, more comprehensible and user-friendly 
versions of this program are  available at . The javadoc is more 
copious, the bug is manifested as an exception and the side effect of 
the bug are more consequential.


This brief version cnosists of just two classes. Here is the JavaFX 
Application class:


***

package bareBonesJavaFXBugExample;


import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;



/**
 * An {@link Application} with one {@link Pane} containing one {@link 
Label}. The {@link Label} has a single {@link 
javafx.event.EventHandler}, {@link LabelEventHandler} which processes 
all {@link MouseEvent}s the {@link Label} receives.

 * 
 * To trigger the bug, run the application, then spend a second mouse 
over the little label in the upper left hand corner of the scrren. You 
will see output to standard I/O. Then, click the label, which will then 
disppear. Check the I/O for Strings ending in debugCounter is 1. 

 * What that String means and how it proves that the JavaFX Application 
Thread has become reentrant is explained in the javadoc of {@link 
LabelEventHandler}.

 */
public class JavaFXAnomalyBareBonesApplication extends Application
{
    public void start(Stage primaryStage)
    {

      Pane mainPane = new Pane();
      mainPane.setMinHeight(800);
      mainPane.setMinWidth(800);

      Label label = new Label(" this is quite a bug ");

      LabelEventHandler labelEventHandler = new 
LabelEventHandler(mainPane, label);

      label.addEventHandler(MouseEvent.ANY, labelEventHandler);

      mainPane.getChildren().add(label);


      Scene scene = new Scene(mainPane);
      primaryStage.setScene(scene);
      primaryStage.show();

    }



    /**
     * The entry point of application.
     *
     * @param args
     *         the input arguments
     */
    public static void main(String[] args)
    {

        launch(args);
    }



}


***

and here is its only dependency, the EventListener class. I included 
enough javadoc to have the program makes sense. :


***

package bareBonesJavaFXBugExample;



import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;

import java.util.Collection;
import java.util.ConcurrentModificationException;

/**
 * An {@link EventHandler} implementation for {@link MouseEvent}s. 
 This implementation's {@link EventHandler#handle(Event)} shows 
the relevant debug information to standard output before and after 
removing the member {@link #label} from the {@link #pane}.

 * 
 * discussion
 * 
 * Users should first satisfy themselves that the value of {@link 
LabelEventHandler#debugCounter} can only be non-zero, in fact 1 (one) 
in the method {@link LabelEventHandler#showDebugInformation(String)} if 
the method {@link LabelEventHandler#handle(MouseEvent)}  has been 
re-entered recursively, that is, before a previous invocation of {@link 
LabelEventHandler#handle(MouseEvent)} has returned.

 * 
 * Proof:  1) debugCounter starts at value 0 
(zero).  2) debugCounter is only incremented once, 
by 1 (one), and that is after the first call to {@link 
LabelEventHandler#showDebugInformation(String)} has returned. 3) 
debugCounter is only decremented once, by 1 (one) and that 
is before the last call to {@link 
LabelEventHandler#showDebugInformation(String)}. 4) however, 
because
 * debugCounter is a class variable ( it's static), if 
handle() is recurvsively re-entered then it's value can be 1 (one) when 
the re-entrant Thread executes {@link 
LabelEventHandler#showDebugInformation(String)}

 * 
 * End proof.
 * 
 * 
 * 
 * The output of this method to standard I/O is volumnious but 
searching the output for the exact String "debugCounter is 1" will 
immediately show the {@link LabelEventHandler#handle(MouseEvent)} 
method to have been recursively entered. 
 * Some other possibilities other than the JavaFX Application Thread 
recursing into {@code handle()} need to be addressed.  One is 
the fact that the compiler is free to reorder statements if it can
 * prove that such a reordering would have no effect on the program's 
correctness.

 * 
 * So somehow the compiler is reordering the increment/decrement of 
{@code  debugCounter} and the calls to {@code   showDebugInformation}. 
 But this would al