problem with two uwps in the same frame on windows

Bug #379472 reported by Nikodemus Siivola
14
This bug affects 2 people
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
High
Unassigned

Bug Description

(defun bad ()
  (unwind-protect
       (catch :oops
         (unwind-protect
              (throw :oops :out)
           t))
    t))

(bad)

; results in...
;
; An exception occurred in context #.(SB-SYS:INT-SAP #X0022E964): #.(SB-SYS:INT-SAP #X0022E950). (Exception code: 3221225513)
; [Condition of type SIMPLE-ERROR]
;
;
; whereas the exact same control flow in two different functions is
; fine

(defun good ()
  (unwind-protect
       (ext)
   t))

(defun ext ()
  (catch :oops
    (unwind-protect
         (throw :oops :out)
      t)))

(good) ; => :OUT

Tags: os-windows
Revision history for this message
Alastair Bridgewater (alastair-bridgewater) wrote :

A fragment of a trace-file for BAD shows:

> IR1 block 4 start c38
>
> IR2 block 10 start c38
> 0: CURRENT-BINDING-POINTER => t2[S36]<t32[EAX]
> 1: SAVE-DYNAMIC-STATE => t3[S35]<t33[EAX] t4[S34]<t34[ECX]
> 2: CURRENT-STACK-POINTER => t1[S37]
> 3: MAKE-UNWIND-BLOCK t35[S19] {#<SB-ASSEM:LABEL 4>} => t36[ECX]
> 4: SET-UNWIND-PROTECT t35[S19]
>
> IR1 block 5 start c56
>
> IR2 block 9 start c56
> 0: CURRENT-BINDING-POINTER => t6[S32]<t37[EAX]
> 1: SAVE-DYNAMIC-STATE => t7[S31]<t38[EAX] t8[S30]<t39[ECX]
> 2: CURRENT-STACK-POINTER => t5[S33]
> 3: MAKE-CATCH-BLOCK t40[S12] ':OOPS!41[Const6]>t42[EDX]
> {#<SB-ASSEM:LABEL 5>}
> => t43[ECX]
>
> IR1 block 6 start c79
>
> IR2 block 8 start c79
>
> IR1 block 7 start c87
>
> IR2 block 7 start c87
> 0: CURRENT-BINDING-POINTER => t10[S28]<t44[EAX]
> 1: SAVE-DYNAMIC-STATE => t11[S27]<t45[EAX] t12[S26]<t46[ECX]
> 2: CURRENT-STACK-POINTER => t9[S29]
> 3: MAKE-UNWIND-BLOCK t47[S5] {#<SB-ASSEM:LABEL 6>} => t48[ECX]
> 4: SET-UNWIND-PROTECT t47[S5]
> 5: MOVE ':OUT!49[Const7]>t50[EDX] => t51[EDX]
> 6: PUSH-VALUES t51[EDX] {1} => t52[EBX] t53[ECX]
> 7: THROW ':OOPS!41[Const6]>t54[EDX] t52[EBX] t53[ECX]

Note the two uses of SET-UNWIND-PROTECT. The first one is for t35[S19], the second for t47[S5]. The values S19 and S5 indicate a negative (expand-down) stack offset within the frame. S19 is [EBP-104] and S5 is [EBP-48]. Win32 is picky about its exception frames, and what this does is disorder the frame chain (the topmost SEH frame is deeper in the stack than the next-topmost SEH frame). We are also lucky that this constraint is only checked for unwind destinations, as if it were checked during full unwind the process would have been killed when choosing any restart from the debugger.

Essentially, I recommend changing the stack frame layout policy and hoping that it fixes the problem.

Revision history for this message
Alastair Bridgewater (alastair-bridgewater) wrote :

I have made two attempts to fix this, neither of which sit very well with me. Initial implementations (including typos and other bugs) of both are available at <http://paste.lisp.org/display/95661>. The first one "works", but is clearly a hack. I do not remember if the second one works, but I can't help but feel that there's a better way to express the required constraint and supporting analysis.

Revision history for this message
Nikodemus Siivola (nikodemus) wrote :
Revision history for this message
Nikodemus Siivola (nikodemus) wrote :
Revision history for this message
Paul Khuong (pvk) wrote :

Should be fixed in ba39d16 (Pack (mostly) stack TNs according to lexical scope information).

Changed in sbcl:
status: Confirmed → Fix Committed
Stas Boukarev (stassats)
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.