Author Topic: vlr-remove not removing Object Reactor inside Callback Function  (Read 9018 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Having spent some time pulling my hair out whilst trying to figure out why my reactor callback functions were continuously being evaluated, I believe I have isolated the issue to a possible bug with the vlr-remove function wherein object reactors are not actually removed by this function.

I have put together the following simple code to demonstrate the issue I am experiencing:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:addreactor ( / en )
  2.     (if (setq en (car (entsel)))
  3.         (setq object-reactor
  4.             (vlr-object-reactor (list (vlax-ename->vla-object en)) "My Object Reactor"
  5.                '((:vlr-modified . mycallback))
  6.             )
  7.         )
  8.     )
  9.     (princ)
  10. )
  11.  
  12. (defun mycallback ( owner reactor params )
  13.     (princ "\nCallback Evaluated.")
  14.     (print (vlr-remove reactor))
  15.     (princ)
  16. )

Steps to recreate problem:
  • Create a circle in the drawing (or any object in fact)
  • Run the above program 'addreactor' and click on the created circle
  • Move the circle
Now, at this point the circle has been modified and so the reactor callback function will be evaluated, printing the message 'Callback Evaluated' at the command-line.

Within the callback function the calling object reactor is removed using vlr-remove, and hence the callback function should no longer be evaluated if the circle is modified again.

However, I find the following unexpected result:

Code - Auto/Visual Lisp: [Select]
  1. Command: _circle Specify center point for circle or [3P/2P/Ttr (tan tan radius)]:
  2. Specify radius of circle or [Diameter]:
  3. Command: addreactor
  4.  
  5. Select object:
  6. Command: m MOVE 1 found
  7.  
  8. Specify base point or [Displacement] <Displacement>:
  9. Specify second point or <use first point as displacement>:
  10. Callback Evaluated.  ;; <-------------- Callback evaluated as expected, Reactor should now be removed.
  11. #<VLR-Object-Reactor> ;; <-------------- vlr-remove returns Reactor Object, indicating removal is successful
  12. Command: m MOVE 1 found
  13.  
  14. Specify base point or [Displacement] <Displacement>:
  15. Specify second point or <use first point as displacement>:
  16. Callback Evaluated.  ;; <--------------  Callback still being evaluated even after reactor is removed.
  17. nil ;; <-------------- vlr-remove returning nil as reactor has already been removed.

This is even weirder:

Code - Auto/Visual Lisp: [Select]
  1. Command: _circle Specify center point for circle or [3P/2P/Ttr (tan tan radius)]:
  2. Specify radius of circle or [Diameter]:
  3. Command: addreactor
  4.  
  5. Select object:
  6. Command: m MOVE 1 found
  7.  
  8. Specify base point or [Displacement] <Displacement>:
  9. Specify second point or <use first point as displacement>:
  10. Callback Evaluated. ;; <--------------  Reactor should now be removed.
  11. #<VLR-Object-Reactor> ;; <-------------- vlr-remove returns Reactor object, indicating removal is successful
  12. Command: (vlr-added-p object-reactor)
  13. nil ;; <-------------- Verifying that Reactor has been removed
  14.  
  15. nil ;; <-------------- Verifying that no Reactors are running
  16.  
  17. Command: m MOVE 1 found
  18.  
  19. Specify base point or [Displacement] <Displacement>:
  20. Specify second point or <use first point as displacement>:
  21. Callback Evaluated. ;; <-------------- Yet callback STILL being evaluated... WTF
  22. nil

Can any of you guys replicate this behaviour? Or maybe spot a mistake in my method?
« Last Edit: August 26, 2012, 08:10:01 AM by Lee Mac »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-remove function not removing Object Reactors
« Reply #1 on: August 25, 2012, 09:18:52 PM »
Same here in ACAD2006.
Using this:
Code: [Select]
(defun c:removeowner (/ en)
  (if (and object-reactor (setq en (car (entsel))))
    (print (vlr-owner-remove object-reactor (vlax-ename->vla-object en)))
  )
  (princ)
)

It works only if the reactor has not been fired, if it has been fired the circle is returned
but the reactor continues to fire.

I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-remove function not removing Object Reactors
« Reply #2 on: August 25, 2012, 09:22:50 PM »
Adding back trace yields nothing useful.
** STRETCH **
Specify stretch point or [Base point/Copy/Undo/eXit]: Backtrace:
[0.18] (VL-BT)
[1.14] (MYCALLBACK #<VLA-OBJECT IAcadCircle 0b8b3a64> #<VLR-Object-Reactor> nil) LAP+7
:CALLBACK-ENTRY.6 (:CALLBACK-ENTRY)
:REACTOR-CALLBACK.3 :REACTOR-CALLBACK

Callback Evaluated.
nil


This is no help
Command: (vlr-remove-all :vlr-object-reactor)
nil

I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove function not removing Object Reactors
« Reply #3 on: August 26, 2012, 07:13:22 AM »
Thank you very much for your time spent testing Alan, I appreciate your assistance  :-)

After some more experimentation on my side, I have further isolated the problem and have found that it only occurs when removing the object reactor from within its callback function.

I tried using the following callback function instead :

Code - Auto/Visual Lisp: [Select]
  1. (defun mycallback ( owner reactor params )
  2.    (princ "\nCallback Evaluated.")
  3.    (princ)
  4. )

And here are is my results from the command-line:

Code - Auto/Visual Lisp: [Select]
  1. Command: _circle
  2. Specify center point for circle or [3P/2P/Ttr (tan tan radius)]:
  3. Specify radius of circle or [Diameter]:
  4. Command: addreactor
  5.  
  6. Select object:
  7. Command: m MOVE 1 found
  8.  
  9. Specify base point or [Displacement] <Displacement>:
  10. Specify second point or <use first point as displacement>:
  11. Callback Evaluated. ;; <-------------- Callback evaluated
  12. Command: (vlr-remove object-reactor) ;; <-------------- Reactor now removed 'manually'
  13. #<VLR-Object-Reactor> ;; <-------------- Reactor removed successfully
  14.  
  15. Command: m MOVE 1 found
  16.  
  17. Specify base point or [Displacement] <Displacement>:
  18. Specify second point or <use first point as displacement>:
  19. ;; <-------------- Callback not evaluated!

So in conclusion at this point:

If vlr-remove is evaluated from within the callback function, the Reactor is 'registered' as being removed (i.e. the VLA Reactor Object is returned and the vlr-remove* functions no longer have any effect) but the Reactor isn't actually removed since the callback is still evaluated.
 
« Last Edit: August 26, 2012, 07:19:28 AM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not Removing Object Reactor inside Callback Function
« Reply #4 on: August 26, 2012, 07:46:18 AM »
After some testing with a Command Reactor, I have found that this problem only appears to apply to removing Object Reactors from within their own callback functions.

Using this code:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:addreactor ( )
  2.     (setq com (vlr-command-reactor "My Command Reactor" '((:vlr-commandended . mycallback))))
  3.     (princ)
  4. )
  5.  
  6. (defun mycallback ( reactor params )
  7.     (princ "\nCallback Evaluated.")
  8.     (vlr-remove reactor)
  9.     (princ)
  10. )

Here are my results:

Code - Auto/Visual Lisp: [Select]
  1. Command: addreactor  ;; <-------------- Command Reactor added.
  2. Command: m MOVE 1 found
  3.  
  4. Specify base point or [Displacement] <Displacement>:
  5. Specify second point or <use first point as displacement>:
  6. Callback Evaluated. ;; <-------------- Callback evaluated, Command Reactor removed.
  7. Command: m MOVE 1 found
  8.  
  9. Specify base point or [Displacement] <Displacement>:
  10. Specify second point or <use first point as displacement>:
  11. ;; <-------------- Callback NOT evaluated

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #5 on: August 26, 2012, 08:27:18 AM »
Now that I have understood that one cannot disable an Object Reactor from within its own callback function, I have managed to implement a working solution in my application by disabling the Object Reactor from another callback function.

I would like to thank the community for their time on this thread, especially CAB's contribution, and I hope that the thread serves as a guide and explanation for others encountering this issue.

Thanks  :-)

Lee

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #6 on: August 26, 2012, 08:51:12 AM »
Good detective work Lee.
But how can you combine reactors or chain them and be sure which is triggered first?
I'm assuming that is how you did it.
(Rather slow here on the weekends  8-) )
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #7 on: August 26, 2012, 09:03:20 AM »
Good detective work Lee.

Thanks Alan  :-)

But how can you combine reactors or chain them and be sure which is triggered first?
I'm assuming that is how you did it.
(Rather slow here on the weekends  8-) )

I used a combination of an Object Reactor triggered by the :vlr-modified event and a Command Reactor triggered on the :vlr-commandended event, and disabled the Object Reactor from within the callback function of the Command Reactor (instead of disabling it from the callback function of the Object Reactor, which sparked this thread topic) before performing the necessary modifications to the owner object and re-enabling the Object Reactor (again from the callback function of the Command Reactor).

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #8 on: August 26, 2012, 09:41:41 AM »
New Development...

I've also just discovered that vlr-remove will fail to remove an Object Reactor if any one of it's owners resides on an Locked Layer.

Steps to recreate this condition:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:addreactor ( / en )
  2.    (if (setq en (car (entsel)))
  3.        (setq object-reactor
  4.            (vlr-object-reactor (list (vlax-ename->vla-object en)) "My Object Reactor"
  5.               '((:vlr-modified . mycallback))
  6.            )
  7.        )
  8.    )
  9.    (princ)
  10. )
  11.  
  12. (defun mycallback ( owner reactor params )
  13.    (princ "\nCallback Evaluated.")
  14.    (princ)
  15. )
  • Create a circle (or any object) in the drawing
  • Run the above code and select the circle
  • Lock the circle's layer
  • Type at the command-line (vlr-remove object-reactor)
  • Unlock the circle's layer and move the circle

Here are my results:
Code - Auto/Visual Lisp: [Select]
  1. Command: _circle
  2. Specify center point for circle or [3P/2P/Ttr (tan tan radius)]:
  3. Specify radius of circle or [Diameter]:
  4. Command: addreactor
  5.  
  6. Select object:
  7.  
  8. ;; <--------- Layer Locked --------->
  9.  
  10. Command: (vlr-remove object-reactor) ;; <-------------- Reactor removed 'manually'
  11. #<VLR-Object-Reactor> ;; <-------------- Indicating reactor has been removed successfully.
  12.  
  13. ;; <--------- Layer Unlocked --------->
  14.  
  15. Command: m MOVE 1 found
  16.  
  17. Specify base point or [Displacement] <Displacement>:
  18. Specify second point or <use first point as displacement>:
  19. Callback Evaluated. ;; <--------------  Callback still being evaluated after reactor is removed.

Note that the Object Reactor is not removed even after using vlr-remove 'manually' at the command-line.

The Solution:

Use vlax-write-enabled-p to check whether owner objects are write enabled before attempting to remove an Object Reactor.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #9 on: August 26, 2012, 10:24:46 AM »
One solution I pondered was to delete the object which kills the reactor.
Then recreate it, not sure you can do all this from within the call back reactor.
No time this morning to test it. Getting ready for the coming weather.

I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #10 on: August 26, 2012, 03:13:56 PM »
One solution I pondered was to delete the object which kills the reactor.
Then recreate it, not sure you can do all this from within the call back reactor.

Thank you for the suggestion, but this wouldn't be possible I'm afraid since the owner object is notifying the Object Reactor and hence cannot be deleted whilst notifying.

Given that I now understand the somewhat stricter rules that apply to manipulating Object Reactors over other Reactors, I know where I stand and can write my applications accordingly to account for this behaviour. Coding applications around known bugs can be annoying, but certainly far less frustrating than not knowing the bug exists and scratching your head as to why things are crashing...

No time this morning to test it. Getting ready for the coming weather.

Ah yes, Isaac has been covered in the news over here too - I wish you all the best and hope the storm passes through safely.

PKENEWELL

  • Bull Frog
  • Posts: 318
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #11 on: August 27, 2012, 01:31:53 PM »
FYI - I get the same Behavior in AutoCAD Mechnical 2013. I don't know what version you are using, but it looks like Autodesk has not fixed it yet.  :-(

Code - Auto/Visual Lisp: [Select]
  1. Command: ADDREACTOR
  2. Select object:
  3. ** STRETCH **
  4. Specify stretch point or [Base point/Copy/Undo/eXit]:
  5. Callback Evaluated.
  6. #<VLR-Object-Reactor>
  7. ** STRETCH **
  8. Specify stretch point or [Base point/Copy/Undo/eXit]:
  9. Callback Evaluated.
  10. nil
  11. nil
  12. ** STRETCH **
  13. Specify stretch point or [Base point/Copy/Undo/eXit]:
  14. Callback Evaluated.
  15. nil
  16.  

Code - Auto/Visual Lisp: [Select]
  1. Command: (defun mycallback ( owner reactor params )
  2. (_>    (princ "\nCallback Evaluated.")
  3. (_>    (princ)
  4. (_> )
  5. MYCALLBACK
  6. CIRCLE
  7. Specify center point for circle or [3P/2P/Ttr (tan tan radius)]:
  8. Specify radius of circle or [Diameter] <1.9370>:
  9. Command: addreactor
  10. Select object:
  11. ** STRETCH **
  12. Specify stretch point or [Base point/Copy/Undo/eXit]:
  13. Callback Evaluated.
  14. Command: *Cancel*
  15. ((:VLR-Object-Reactor #<VLR-Object-Reactor>))
  16. ** STRETCH **
  17. Specify stretch point or [Base point/Copy/Undo/eXit]:
  18.  
"When you are asked if you can do a job, tell 'em, 'Certainly I can!' Then get busy and find out how to do it." - Theodore Roosevelt

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #12 on: August 27, 2012, 01:38:26 PM »
Thank you for your time testing it Phil, your results in 2013 and CAB's results in 2006 confirm my suspicions that these are indeed bugs present in most, if not all, versions of AutoCAD and its derivative programs.

Since LISP is no longer in development I very much doubt these issues will be fixed any time soon, though, at least we are now aware of them and can code around them.

Thanks  :-)

PKENEWELL

  • Bull Frog
  • Posts: 318
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #13 on: August 27, 2012, 01:49:35 PM »
Thank you for your time testing it Phil, your results in 2013 and CAB's results in 2006 confirm my suspicions that these are indeed bugs present in most, if not all, versions of AutoCAD and its derivative programs.

Since LISP is no longer in development I very much doubt these issues will be fixed any time soon, though, at least we are now aware of them and can code around them.

Thanks  :-)

Very True. Thanks to you as well for discovering the issue. Saves the rest of us the frustration of discovering it ourselves.   :lol:
"When you are asked if you can do a job, tell 'em, 'Certainly I can!' Then get busy and find out how to do it." - Theodore Roosevelt

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #14 on: August 27, 2012, 02:01:19 PM »
Saves the rest of us the frustration of discovering it ourselves.   :lol:

Believe me... there was frustration in abundance before this thread was started  :ugly:

LE3

  • Guest
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #15 on: August 27, 2012, 02:02:22 PM »
not a help at all - but recall seeing this, back on vital lisp too - don't remember if i ever end up doing anything for all my vlisp-reactors code in the past.

glad you still having fun with a-vlisp - cheers!

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #16 on: August 27, 2012, 02:04:18 PM »
Cheers Luis  :-)

glad you still having fun with a-vlisp - cheers!

I've tried to overcome the addiction many a time, but LISP still has me hooked  8-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #17 on: August 27, 2012, 02:19:16 PM »
Thank you for your time testing it Phil, your results in 2013 and CAB's results in 2006 confirm my suspicions that these are indeed bugs present in most, if not all, versions of AutoCAD and its derivative programs.

Since LISP is no longer in development I very much doubt these issues will be fixed any time soon, though, at least we are now aware of them and can code around them.

Thanks  :-)

Can modifying the reactor status be viewed as modifying the object & therefore not allowed while in the callback function?  8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #18 on: August 27, 2012, 02:32:13 PM »
Can modifying the reactor status be viewed as modifying the object & therefore not allowed while in the callback function?  8-)

Given the similar behaviour experienced when an owner object resides on a locked layer, that would be a very plausible explanation for this problem Alan. Though, the major underlying issue is that the vlr-remove function reports that the reactor has been removed successfully, instead of throwing an error, and as a result the reactor cannot then be removed by any means other than to close the drawing.

In conclusion:

When using Object Reactors:
  • Do not attempt to remove the reactor from within the reactor callback function.
  • Verify that all owner objects of an Object Reactor are write enabled before attempting to remove the reactor.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #19 on: August 27, 2012, 02:38:53 PM »
the reactor cannot then be removed by any means other than to close the drawing.
You can delete the object and recreate it.

Good detective work Lee.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.


LE3

  • Guest

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #22 on: August 27, 2012, 05:40:50 PM »
the reactor cannot then be removed by any means other than to close the drawing.
You can delete the object and recreate it.

You could, but that wouldn't actually remove the Object Reactor, only set the erase flag on the owner object(s) - they would still be owners to the Object Reactor and the Reactor would still be active in the drawing, to demonstrate:

Code - Auto/Visual Lisp: [Select]
  1. Command: _circle
  2. Specify center point for circle or [3P/2P/Ttr (tan tan radius)]:
  3. Specify radius of circle or [Diameter]:
  4. Command: addreactor  ;; <-------------- Circle is now owner of Object Reactor
  5.  
  6. Select object:
  7. Command: _.erase 1 found ;; <-------------- Circle deleted
  8.  
  9. Callback Evaluated. ;; <-------------- Callback evaluated on deletion (modification) of circle
  10. Command: (vlr-owners object-reactor)
  11. (#<VLA-OBJECT IAcadCircle 0e81c314>) ;; <-------------- Circle still owner of Object Reactor after deletion

Good detective work Lee.

Cheers Alan, you too  :-)


LE3

  • Guest
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #24 on: August 27, 2012, 07:58:36 PM »
played on this a little and maybe thinking a bit too and went to read the help...

Code - Auto/Visual Lisp: [Select]
- will disable the reactor(s) only.

and maybe could it be a good idea to test if it is enabled, before doing any work inside of the callback:
Code - Auto/Visual Lisp: [Select]
  1. (defun mycallback  (owner reactor params)
  2. (if (vlr-added-p reactor)

so, inside of the callback, one might want to check if the reactor was disabled? first, and that's what has been provided always, a way to disabled the reactors and enabled them for later use, this means that the reactors are still there, unless they are actually removed outside by other means using:

Code - Auto/Visual Lisp: [Select]

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #25 on: August 28, 2012, 06:37:24 AM »
Code - Auto/Visual Lisp: [Select]
- will disable the reactor(s) only.

and maybe could it be a good idea to test if it is enabled, before doing any work inside of the callback:
Code - Auto/Visual Lisp: [Select]
  1. (defun mycallback  (owner reactor params)
  2. (if (vlr-added-p reactor)

so, inside of the callback, one might want to check if the reactor was disabled?

I would agree, except that in this case vlr-remove / vlr-remove-all don't appear to disable the reactors if called from within the callback function, or if an owner is on a locked layer.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #26 on: August 28, 2012, 06:50:17 AM »
Yep, I think the issue is that object reactors are linked to objects using entity data (in this case a dictionary). And if you want to edit the entity data (i.e. remove the reactor) you need a write lock on that entity. But since the reactor fires, it already has a read-lock since it just read the data of the reactor. Therefore the write-lock cannot be obtained and the edit fails.

You might have to remove the reactor from somewhere else. I.e. when it has finished and the locks are released. Though where to do this I'm not sure - would have been a perfect place for a timer-reactor  :ugly:
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: vlr-remove not removing Object Reactor inside Callback Function
« Reply #27 on: August 28, 2012, 07:00:56 AM »
You might have to remove the reactor from somewhere else. I.e. when it has finished and the locks are released. Though where to do this I'm not sure...

Reply#7  :wink: