commit 8baa1fe68c54ea462996d8e2632803de69ee080e
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Tue Apr 4 15:57:33 2017 +0100

    When detaching Nodes, do make sure we also cancel any ATTACH jobs that might be pending.

diff --git a/src/main/java/org/distorted/library/DistortedAttachDaemon.java b/src/main/java/org/distorted/library/DistortedAttachDaemon.java
index dce57fc..172f7a9 100644
--- a/src/main/java/org/distorted/library/DistortedAttachDaemon.java
+++ b/src/main/java/org/distorted/library/DistortedAttachDaemon.java
@@ -83,6 +83,30 @@ class DistortedAttachDaemon
     return ( num>0 );
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  static void cancelAttachJobs(DistortedAttacheable a, DistortedEffects e)
+    {
+    int num = mJobs.size();
+    Job job;
+
+    for(int i=0; i<num; i++)
+      {
+      job = mJobs.get(i);
+
+      if( job.type == ATTACH && job.attacheable==a )
+        {
+        DistortedEffects effects = job.object.getEffects();
+
+        if( effects.getID() == e.getID() )
+          {
+          mJobs.remove(i);
+          break;
+          }
+        }
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   static void attach(DistortedAttacheable a, DistortedNode n)
diff --git a/src/main/java/org/distorted/library/DistortedNode.java b/src/main/java/org/distorted/library/DistortedNode.java
index 02e7426..dd7630e 100644
--- a/src/main/java/org/distorted/library/DistortedNode.java
+++ b/src/main/java/org/distorted/library/DistortedNode.java
@@ -443,6 +443,7 @@ public class DistortedNode implements DistortedAttacheable
     {
     long id = effects.getID();
     DistortedNode node;
+    boolean detached= false;
 
     for(int i=0; i<mNumChildren[0]; i++)
       {
@@ -450,10 +451,18 @@ public class DistortedNode implements DistortedAttacheable
 
       if( node.mEffects.getID()==id )
         {
+        detached=true;
         DistortedAttachDaemon.detach(this,node);
         break;
         }
       }
+
+    if( !detached )
+      {
+      // if we failed to detach any, it still might be the case that
+      // there's a job in Daemon's queue that we need to cancel.
+      DistortedAttachDaemon.cancelAttachJobs(this,effects);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/DistortedOutputSurface.java b/src/main/java/org/distorted/library/DistortedOutputSurface.java
index f28ce4b..a682dac 100644
--- a/src/main/java/org/distorted/library/DistortedOutputSurface.java
+++ b/src/main/java/org/distorted/library/DistortedOutputSurface.java
@@ -448,6 +448,7 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
     {
     long id = effects.getID();
     DistortedNode node;
+    boolean detached = false;
 
     for(int i=0; i<mNumChildren; i++)
       {
@@ -455,10 +456,18 @@ abstract class DistortedOutputSurface extends DistortedSurface implements Distor
 
       if( node.getEffects().getID()==id )
         {
+        detached = true;
         DistortedAttachDaemon.detach(this,node);
         break;
         }
       }
+
+    if( !detached )
+      {
+      // if we failed to detach any, it still might be the case that
+      // there's a job in Daemon's queue that we need to cancel.
+      DistortedAttachDaemon.cancelAttachJobs(this,effects);
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
