Re: [Oorexx-devel] Question ad new ThrowException API...

2022-08-13 Thread Rick McGuire
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...

2022-08-13 Thread Rony G. Flatscher

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...

2022-08-13 Thread Rick McGuire
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