Re: [Oorexx-devel] Question ad new ThrowException API...
On Sat, Aug 13, 2022 at 10:44 AM Rony G. Flatscher wrote: > On 13.08.2022 15:16, Rick McGuire wrote: > > On Sat, Aug 13, 2022 at 8:45 AM Rony G. Flatscher > wrote: > >> E.g. rxapi.pdf "1.17.189. *NEW* ThrowException/0/1/2" states: "Throw a >> SYNTAX condition. The API call doesn't return and the current method, >> routine, or exit is exited immediately.". >> >> Testing ThrowException1() however will end the running Rexx program >> immediately not the current call, here the calling sequence: >> >>- test.rex requires some testpkg.cls, creating an object o of a class >>residing in testpkg.cls >>- test.rex will send an unknown message with two arguemtns to o >>causing the unknown method to call a routine in the native code >>- the native code will cause a runtime exception to be thrown if one >>of the two arguments has the value 1 >> >> Using RaiseException1() will cause that exception to be raised and the >> control gets back to the unknown method and then back to test.rex. >> >> Using ThrowException1() however will cause ending Rexx altogether as if >> it causes not only the call to the native routine to be exited immediately, >> but also the unknown method from which the call started and info.rex where >> o's unknown method gets invoked from. Is that to be expected? >> > Are you using the correct context instance when calling ThrowExeption()? > That's the behavior I would expect if an instance other than the context > for the external call was used. > > Hmm, good question! > > Here is what is done in this test program (trying to get a small, > self-contained example that would exhibit the reported behaviour, WIP): > >- define a RexxRoutine in native code that makes its RexxInstance >globally available with 'ri', then calls a plain function with the >following signature "RexxObjectPtr work(RexxCallContext *rcc, RexxObjectPtr >o, int64_t val)" > >- work() will use the RexxInstance to carry out an >ri->AttachThread() which will be used to send a message to the supplied >object 'o'; if val has the value 1, then an unknown message gets sent to > 'o' > > Why are you doing an AttachThread()? This is totally unnecessary and deactivates the current thread stack. Using the attached thread to raise an exception will not percolate back to the calling routine because you just drew a line in the sand. If you need to raise something in the caller, they you will need to do a DetachThread() and use the original call context to raise the exception. Rick > >- >- if rtc->CheckCondition() is true, then a debug message is shown > followed by the rcc->RaiseException1() call before returning; using > rcc->ThrowException1() instead ends the entire Rexx program as reported, > although the RexxCallContext gets used for it > > - however, doing a rtc->DetachThread() before calling > rcc->ThrowException1() will yield the documented behaviour! > > > > This could also explain some of the problems you've been seeing with your > calls. > > No, what happens in the bridge is the following: > >- for each Rexx instance a peer Java instance gets created. If there >is a callback to Rexx the native code fetches the appropriate Rexx instance >and carries out an AttachThread(), interact with ooRexx (e.g. sending an >ooRexx object a message) and will do a matching DetachThread() prior to >returning from the native code, > >- the invoked Rexx code (some Rexx method) may be calling back again >into Java and if on the Java side there is a callback to Rexx needed, the >same as above occurs recursively, > >- eventually returning from (possibly nesting) callbacks. > > In the case that a call to Java causes an exception to be thrown on the > Java side an appropriate RaiseException gets prepared and raised such that > upon return from Java that condition can be trapped on the Rexx side (and > access to the Java Throwable becomes possible). > > The RaiseException gets prepared and raised in another native function > that is written to deal with either a RexxCallContext or a RexxExitContext > (Java implemented command and exit handlers are fully supported) with an > argument indicating which type of context is currently supplied. In the > past (and it used to work) RaiseCondition1() was invoked using the > RexxThreadContext (fetching it e.g. with "((RexxCallContext *) > argCtxt)->threadContext" to simplify the native code by using the > threadContext for plain vanilla calls to e.g. ArrayPut, FindClass, > NewArray, ReleaseLocalReference, SendMessage1, String, StringLength, > StringData and the like). A few days ago I have changed it to use the > supplied contexts to invoke RaiseException1(), which did not make a > difference, unfortunately. (As reported SetContextVariable() works and > upon return to Rexx the BSF_ERROR_STRING variable can be used.) > > As the condition does not get raised it is also not possible to get at the
Re: [Oorexx-devel] Question ad new ThrowException API...
On 13.08.2022 15:16, Rick McGuire wrote: On Sat, Aug 13, 2022 at 8:45 AM Rony G. Flatscher wrote: E.g. rxapi.pdf "1.17.189. *NEW* ThrowException/0/1/2" states: "Throw a SYNTAX condition. The API call doesn't return and the current method, routine, or exit is exited immediately.". Testing ThrowException1() however will end the running Rexx program immediately not the current call, here the calling sequence: * test.rex requires some testpkg.cls, creating an object o of a class residing in testpkg.cls * test.rex will send an unknown message with two arguemtns to o causing the unknown method to call a routine in the native code * the native code will cause a runtime exception to be thrown if one of the two arguments has the value 1 Using RaiseException1() will cause that exception to be raised and the control gets back to the unknown method and then back to test.rex. Using ThrowException1() however will cause ending Rexx altogether as if it causes not only the call to the native routine to be exited immediately, but also the unknown method from which the call started and info.rex where o's unknown method gets invoked from. Is that to be expected? Are you using the correct context instance when calling ThrowExeption()? That's the behavior I would expect if an instance other than the context for the external call was used. Hmm, good question! Here is what is done in this test program (trying to get a small, self-contained example that would exhibit the reported behaviour, WIP): * define a RexxRoutine in native code that makes its RexxInstance globally available with 'ri', then calls a plain function with the following signature "RexxObjectPtr work(RexxCallContext *rcc, RexxObjectPtr o, int64_t val)" * work() will use the RexxInstance to carry out an ri->AttachThread() which will be used to send a message to the supplied object 'o'; if val has the value 1, then an unknown message gets sent to 'o' o if rtc->CheckCondition() is true, then a debug message is shown followed by the rcc->RaiseException1() call before returning; using rcc->ThrowException1() instead ends the entire Rexx program as reported, although the RexxCallContext gets used for it o however, doing a rtc->DetachThread() before calling rcc->ThrowException1() will yield the documented behaviour! This could also explain some of the problems you've been seeing with your calls. No, what happens in the bridge is the following: * for each Rexx instance a peer Java instance gets created. If there is a callback to Rexx the native code fetches the appropriate Rexx instance and carries out an AttachThread(), interact with ooRexx (e.g. sending an ooRexx object a message) and will do a matching DetachThread() prior to returning from the native code, * the invoked Rexx code (some Rexx method) may be calling back again into Java and if on the Java side there is a callback to Rexx needed, the same as above occurs recursively, * eventually returning from (possibly nesting) callbacks. In the case that a call to Java causes an exception to be thrown on the Java side an appropriate RaiseException gets prepared and raised such that upon return from Java that condition can be trapped on the Rexx side (and access to the Java Throwable becomes possible). The RaiseException gets prepared and raised in another native function that is written to deal with either a RexxCallContext or a RexxExitContext (Java implemented command and exit handlers are fully supported) with an argument indicating which type of context is currently supplied. In the past (and it used to work) RaiseCondition1() was invoked using the RexxThreadContext (fetching it e.g. with "((RexxCallContext *) argCtxt)->threadContext" to simplify the native code by using the threadContext for plain vanilla calls to e.g. ArrayPut, FindClass, NewArray, ReleaseLocalReference, SendMessage1, String, StringLength, StringData and the like). A few days ago I have changed it to use the supplied contexts to invoke RaiseException1(), which did not make a difference, unfortunately. (As reported SetContextVariable() works and upon return to Rexx the BSF_ERROR_STRING variable can be used.) As the condition does not get raised it is also not possible to get at the Java throwable object (available at the second index position in the additional array) and as such it is not possible to find out the root cause of a Java exception. If so, when would one want to use ThrowException[0|1|2|3] over RaiseException[0|1|2|3]? I would want to use it if I don't want to worry about unwinding my call chain to do a normal return. Ok! But, if there are malloc() calls in the call chain that need to have matching free() calls then ThrowException() should probably not be used. ---rony ___
Re: [Oorexx-devel] Question ad new ThrowException API...
On Sat, Aug 13, 2022 at 8:45 AM Rony G. Flatscher wrote: > E.g. rxapi.pdf "1.17.189. *NEW* ThrowException/0/1/2" states: "Throw a > SYNTAX condition. The API call doesn't return and the current method, > routine, or exit is exited immediately.". > > Testing ThrowException1() however will end the running Rexx program > immediately not the current call, here the calling sequence: > >- test.rex requires some testpkg.cls, creating an object o of a class >residing in testpkg.cls >- test.rex will send an unknown message with two arguemtns to o >causing the unknown method to call a routine in the native code >- the native code will cause a runtime exception to be thrown if one >of the two arguments has the value 1 > > Using RaiseException1() will cause that exception to be raised and the > control gets back to the unknown method and then back to test.rex. > > Using ThrowException1() however will cause ending Rexx altogether as if it > causes not only the call to the native routine to be exited immediately, > but also the unknown method from which the call started and info.rex where > o's unknown method gets invoked from. Is that to be expected? > Are you using the correct context instance when calling ThrowExeption()? That's the behavior I would expect if an instance other than the context for the external call was used. This could also explain some of the problems you've been seeing with your calls. > If so, when would one want to use ThrowException[0|1|2|3] over > RaiseException[0|1|2|3]? > I would want to use it if I don't want to worry about unwinding my call chain to do a normal return. Rick > ---rony > > ___ > Oorexx-devel mailing list > Oorexx-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/oorexx-devel > ___ Oorexx-devel mailing list Oorexx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/oorexx-devel