Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem calling error handler from BEGIN...END SEQUENCE #1673

Open
cpyrgas opened this issue Jan 24, 2025 · 3 comments
Open

Problem calling error handler from BEGIN...END SEQUENCE #1673

cpyrgas opened this issue Jan 24, 2025 · 3 comments
Assignees
Labels

Comments

@cpyrgas
Copy link

cpyrgas commented Jan 24, 2025

https://www.xsharp.eu/forum/topic?p=32646#p32646

Following code prints in X#:

before BEGIN SEQUENCE .F. 
in BEGIN SEQUENCE .T. 
in RECOVER .F. 
after END SEQUENCE .F. 

so the ErrorHandler() function is not called at all, as it does in VO:

before BEGIN SEQUENCE .F. 
in BEGIN SEQUENCE .T. 
in ErrorHandler .T. // why is this line missing in X#?
in RECOVER .F. 
after END SEQUENCE .F. 
FUNCTION Start()  AS INT
	LOCAL oCB AS CODEBLOCK
	LOCAL err AS USUAL

	oCB := ErrorBlock( {|err| ErrorHandler(err) } )
	? "before BEGIN SEQUENCE", CanBreak()
	BEGIN SEQUENCE
		? "in BEGIN SEQUENCE", CanBreak()
		Error{}:Throw()
	RECOVER USING err      
		? "in RECOVER", CanBreak()
	END SEQUENCE
	ErrorBlock( oCB )
	?  "after END SEQUENCE", CanBreak() 
RETURN 0
	
FUNCTION ErrorHandler(err) AS USUAL
	?  "in ErrorHandler", CanBreak() 
	_Break(err)
	?  "in ErrorHandler after _break", CanBreak() 
RETURN NIL
@cpyrgas cpyrgas changed the title Problem calling error handler from EBGIND...END SEQUENCE Problem calling error handler from BEGIN...END SEQUENCE Jan 24, 2025
cpyrgas pushed a commit that referenced this issue Jan 24, 2025
@RobertvanderHulst RobertvanderHulst self-assigned this Jan 24, 2025
@RobertvanderHulst
Copy link
Member

Some comments:
This should have worked as expected when the /vo17 compiler option (VO compatible BEGIN SEQUENCE .. END SEQUENCE) was enabled, but I see now that the code that gets generated is not correctly doing what it is supposed to do.

RobertvanderHulst added a commit that referenced this issue Jan 29, 2025
* SqlRdd updates

* [Compiler] Simplified Keyword Rule (no need for separate rules for Base, Xpp, Fox). These is now a single rule for "soft" keywords.
Added ThisForm keyword for FoxPro.  The detection and translation is done in the TransformationFox. The implementation of the FindForm() call is inside the code that also handles Clipper arguments and PSZs inside TransformationRT.
See https://www.xsharp.eu/forum/topic/5213

* [Tests] Adjust tests to work with X# 3:
- Added method FindForm() for code that uses ThisForm
- Cannot use .cs extension for source file
- Disable an extra warning
-

* [Compiler tests] Added C934 for #1673

* [Compiler tests] Added C935 for #1677

* [XGui] Suppress wndproc because current code disables mouse move messages on fixed text controls

* [Compiler] Fix for C935 and #1677 . The hascode is now calculated for the full filename including the path. Previously the hashcode was for the path only.

---------

Co-authored-by: cpyrgas <[email protected]>
@SUngemach
Copy link

AFAIK the errorhandler is being called - only CanDefault() is FALSE during its execution and _break() thus doesn't jump to RECOVER but exits the application.

My current workaround ist this:

FUNCTION _SequenceError(e AS Exception) AS USUAL
    LOCAL oError AS error
    LOCAL uRueck AS USUAL
    
    oError := error{e}
    aadd( gaErrorProcLineInfo, getErrorProcLineInfo( oError ) )
    uRueck := eval( ErrorBlock(), oError )
    asize( gaErrorProcLineInfo, max(0,alen( gaErrorProcLineInfo )-1 ) )
    
    RETURN u

This calls a function retrieving the actual error line (because later in the errorhandler the call stack points to the BEGIN SEQUENCE line in stead of the one which threw the error) and puts it on a stack before moving on to the real error handler. Our own stack handler reads this and makes sure that any stack in protocols which are written during error handling remains useful.

We also have replaced _break() with _ErrorBlockAwareBreak everywhere in our code:

FUNCTION _ErrorBlockAwareBreak( uValue := NIL AS USUAL ) AS VOID
    IF CanBreak() .OR. Empty( gaErrorProcLineInfo )
        _break( uValue )
    ENDIF
    RETURN

This makes the code in the called errorblock() running to its end and then jumping back to RECOVER USING. It would also still work once CanBreak() delivers a true value in the future. It's not satisfying, though, because we needed to modify all our errorhandlers because now code after a _break() call would still be executed. IMO all this could be solved if CanBreak() and _break() behave properly.

@RobertvanderHulst
Copy link
Member

Stefan,
I am aware of this. Unfortunately, this requires a not so easy change in the compiler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants