Jump to content

Error trapper undoing too much...


lamensterms

Recommended Posts

Hey,

 

We're having an ongoing issue with some of our LISP routines, specifically the error trapper/handler. The problem is that sometimes upon 'error', too many actions will be undone.

 

My assumption is... (and I'm happy to have this disputed)... one LISP routine's error handler is using "UNDO" "BACK", but the routine itself does not place an "UNDO" "MARK".

 

So upon 'error' the trapper is issuing "UNDO" "BACK" and undoing to the previous MARK set, not one that should be in the routine being crashed. Does this sound right?

 

Having said all that, does anyone have any suggestions on how to find which routine would be stuffing it up? Below is the code for a routine that undid everything (well.. back to the previous mark) upon 'error'. But this routine does have a "UNDO" "MARK" set... so it shoot my theory down.

 

Either way, I'm struggling to solve this one and would greatly appreciate any help in uneathing the guilty routine.

 

Thanks a lot.

 

(defun uzerr (s)
(command "undo" "b")
(prompt "\n*Program Terminated***UZ.lsp ERROR MESSAGE*")
(setq *error* exi)
(princ)
)

(Defun c:UZ (/ pnt1 pnt2 os orth)
(setq uzcmde (getvar "cmdecho"))
(setvar "cmdecho" 0)
(command "undo" "m")
(setq exi *error*)
(setq *error* uzerr)
(setq OS (getvar "osmode"))
(setq ORTH (getvar "orthomode"))
(setvar "osmode" 512)
(command "UCSICON" "ON")
(setq PNT1 (getpoint "\nPick first point, nearest to - or press enter to turn off nearest osnap..."))
(setvar "orthomode" 0)
(if (= PNT1 nil)
(progn
 (setvar "osmode" OS)
 (prompt "\nPick two points to align X axis...")
 (command "ucs" "z" pause pause)
) 
(progn
 (initget 1)
 (setq PNT2 (getpoint PNT1 "\nPick second point - Nearest to ..."))
 (setvar "osmode" 0)
 (command "ucs" "z" PNT1 PNT2)
 (setvar "osmode" OS)
)
)
(setvar "orthomode" ORTH)
(setq *error* exi)
(setvar "cmdecho" uzcmde)
(princ)
)

Link to comment
Share on other sites

  • 1 month later...

After a little more investigation (and education - thanks to Lee Mac's article here... http://www.lee-mac.com/errorhandling.html) I have now realised that none of my LISP routines have the temporary *error* function/symbol defined as a local variable. So some (and I'm guessing there will be a few) of my routines are defining *error* as the temporary function, specific to that routine, but are then not restoring *error* to its default function.

 

This explains the issues I've had with UNDO > BACK (being that I have had a temporary *error* function set, while it should be set to default).

Link to comment
Share on other sites

After a little more investigation (and education - thanks to Lee Mac's article here... http://www.lee-mac.com/errorhandling.html) I have now realised that none of my LISP routines have the temporary *error* function/symbol defined as a local variable. So some (and I'm guessing there will be a few) of my routines are defining *error* as the temporary function, specific to that routine, but are then not restoring *error* to its default function.

 

Although you are not following the route of declaring the *error* symbol local to the function, your current code still follows the method I describe under the heading 'An Alternative to Function Localisation', so the previous *error* function will still be restored. :thumbsup:

Link to comment
Share on other sites

Thanks Lee. I think the example code I originally posted may not be an offending routine.

 

I've got some routines that I believe are not closing out completely. For example, I've got a routine that initiates Block Edit, and I think the Block Editor is launched before the routine calls for the *error* symbol to be restored to default. I understand (or, I hope I understand), that localising of the *error* symbol will remedy that particular case.

 

Happy to be steered in the right direction though.

 

Thanks a lot for the reply.

Link to comment
Share on other sites

  • 9 months later...

Hey again guys.

I just lost a long, detailed post so forgive me if this one is a little brief.

We are still having this issue.

I'm at a bit of a loss, as time goes on, and I correct more erroneous routines, we should be seeing this problem less and less, but it still pops up occasionally. Now I'm starting to doubt if I actually understand the problem at all.

Does anyone have any advice on another approach to correct this problem? Or how to identify the offending routines to fix?

I have read here: http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/misbehaving-undo-mark/td-p/863544 ... that it's not wise to use UNDO MARK in LISP routines. Is there any truth to that? I followed AFRALISP's error handler example for UNDO MARK & BACK, should I change to UNDO BEGIN & END?

Any other advice would be greatly appreciated.

Link to comment
Share on other sites

I always use the vla-EndUndoMark/vla-StartUndoMark methods, check this fragment with description from Lee:

(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(if (= 8 (logand 8 (getvar 'undoctl))) ;; If an undo group is already open
 (vla-endundomark doc) ;; close it
) ;; end if
(vla-startundomark doc) ;; Open a new undo group
(vla-endundomark doc) ;; Close the open undo group

Where between Start and Endundomark must be located the expressions, that perform changes on the drawing (like changing object's property value).

Also I think that when using the UNDO command, a command-s call must be used when its within the *error* function, otherwise something like this is enough:

  (defun *error* ( msg )
   (and acDoc (= 8 (logand (getvar 'undoctl) ) (vla-EndUndoMark acDoc))
   (princ msg)
   (princ)
 )

Link to comment
Share on other sites

I think I've been able to reproduce this error now, and have found some confusing clues/results:

 

There are 3 LISP routines used in these tests, please see below:

 

CODE#1

(defun C:BI2NOSCALING (/)
(SETVAR "CMDECHO" 0)
  (prompt "\nPICK INSERTION POINT. ")
  (SETQ SCALE "1") 
(SETVAR "CMDECHO" 1)
  (COMMAND "INSERT" BLOCK pause "" scale pause)
(SETVAR "CMDECHO" 0)
(command "explode" "L")
  (terpri)
)

CODE#2

(defun c:mi ( / *error* MIss MIpt1 MIpt2 OROS ORORT)
(SETQ OROS (GETVAR "OSMODE"))
(SETQ ORORT (GETVAR "ORTHOMODE"))
(command "undo" "m")
;(command "undo" "m")
(SETVAR "OSMODE" 0)
(SETVAR "ORTHOMODE" 1)
(SETVAR "cmdecho" 0)
;(COMMAND "undo" "END")
(setq exi *error*)
(setq *error* MIerr)
(setq MIss (ssget))
(setq MIpt1 (getpoint))
(command "ucs" "O" MIpt1)
(setq MIpt2 '( 0 0 0))
(SETVAR "cmdecho" 1)
(command "mirror" MIss "" MIPT2 pause pause)
(command "ucs" "P")
(SETVAR "OSMODE" OROS)
(SETVAR "ORTHOMODE" ORORT)
(SETVAR "cmdecho" 0)
(setq *error* exi)
(princ)
)

CODE#3

(defun c:mi ( / *error* MIss MIpt1 MIpt2 OROS ORORT)
(SETQ OROS (GETVAR "OSMODE"))
(SETQ ORORT (GETVAR "ORTHOMODE"))
(command "undo" "m")
(command "undo" "m")
(SETVAR "OSMODE" 0)
(SETVAR "ORTHOMODE" 1)
(SETVAR "cmdecho" 0)
;(COMMAND "undo" "END")
(setq exi *error*)
(setq *error* MIerr)
(setq MIss (ssget))
(setq MIpt1 (getpoint))
(command "ucs" "O" MIpt1)
(setq MIpt2 '( 0 0 0))
(SETVAR "cmdecho" 1)
(command "mirror" MIss "" MIPT2 pause pause)
(command "ucs" "P")
(SETVAR "OSMODE" OROS)
(SETVAR "ORTHOMODE" ORORT)
(SETVAR "cmdecho" 0)
(setq *error* exi)
(princ)
)

 

Error Handler

(defun MIerr (s)
(command "undo" "b")
(prompt "\n*Program Terminated***Mirror.lsp ERROR MESSAGE*")
(setq *error* exi)
(princ)
)

Test 1 - No Problem Produced

In a new drawing (no undo history), if I run CODE#1 completely, then CODE#2 but ESC out of routine at prompt for 2nd point... No problem.

 

Test 2 - No Problem Produced

In a new drawing (no undo history), if I run CODE#1 completely, then CODE#3 but ESC out of routine at prompt for 2nd point... No problem.

 

Test 3 - Problem Produced

In a new drawing (no undo history), if I run CODE#1 completely, then hit RETURN & then ESC, then run CODE#2 but ESC out of routine at prompt for 2nd point... Problem.

 

Test 4 - No Problem Produced

In a new drawing (no undo history), if I run CODE#1 completely, then hit RETURN & then ESC, then run CODE#3 but ESC out of routine at prompt for 2nd point... No Problem.

 

I'm finding it hard to make sense out of this, but my observations are: if I ESC out of CODE#1 before ESCing out of CODE#2, the problem occurs. But it I ESC out of CODE#1 before ESCing out of CODE#3, no problem occurs. The only difference between CODE#2 & CODE#3 is that CODE#3 has the (command "undo" "m") line duplicated. It seems that there is a possibility that a single (command "undo" "m") line will be ignored (or something). But if I run CODE#2 after successfully completing the previous command... no problem.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...