I'm looking for help to better understand how to fix bugs:#1362
<https://sourceforge.net/p/oorexx/bugs/1362/>, I'm printf-tracing some
`Activity` and `RexxActivation` functions (see attached patch) for
`signal/call on ERROR` and – for comparison – for `signal/call on HALT`
with attached script.

(In case you wonder, why I'm not using signal/call on ANY` as the bug
description says: the issue seems to be related to the HALT condition, not
being be specific to ANY)


The trace for SIGNAL ON ERROR looks straight-forward:
the condition is raised, it is confirmed it will be trapped, trap() is
called and Rexx returns the expected message

~~~
> TstBug1362-select signal error
Activity::raiseCondition: will be trapped
Activity::raiseCondition(DirectoryClass): calling trap()
Activity::raiseCondition(DirectoryClass): calling trap()
RexxActivation::run: catch (RexxActivation *t)
RexxActivation::run: call processTraps()
RexxActivation::processTraps(): entry
RexxActivation::processTraps(): i=0
COND: condition ERROR raised on line 17, desc 'exit 1', add 'The NIL object'
~~~


Similar, the the trace for CALL ON ERROR shows
the condition is raised, it is confirmed it will be trapped, trap() is
called, and as this is a CALL (not SIGNAL) processing is delayed until
ClauseBoundary; at ClauseBoundary the trap is processed, Rexx returns the
expected message, and continues

~~~
> TstBug1362-select call error
Activity::raiseCondition: will be trapped
Activity::raiseCondition(DirectoryClass): calling trap()
Activity::raiseCondition(DirectoryClass): calling trap()
RexxActivation::trap isCall -> clauseBoundary = true
Activity::raiseCondition(DirectoryClass): (CALL ON - only) returning 1
RexxActivation::processClauseBoundary: entry
RexxActivation::processClauseBoundary: call processTraps()
RexxActivation::processTraps(): entry
RexxActivation::processTraps(): i=0
COND: condition ERROR raised on line 17, desc 'exit 1', add 'The NIL object'
RexxActivation::processClauseBoundary: conditionQueue->isEmpty 1
returning
~~~


The trace for SIGNAL ON HALT looks a little bit suspicious to me: HALT is
detected (though initially no RaiseCondition() is called), and processing
is delayed until ClauseBoundary (is that to be expected for SIGNAL)?
Next, trapping is confirmed, but again, processing is delayed until
ClauseBoundary (unexpected for me).  Upon next ClauseBoundary Rexx returns
the expected message

~~~
> TstBug1362-select signal halt
Activity::halt: NULL
RexxActivation::halt: clauseBoundary = true
RexxActivation::processClauseBoundary: entry
RexxActivation::processClauseBoundary: conditionQueue == OREF_NULL
RexxActivation::processClauseBoundary: settings.haveHaltCondition()
Activity::raiseCondition: will be trapped
Activity::raiseCondition(DirectoryClass): calling trap()
RexxActivation::trap HALT checking exit
RexxActivation::run: catch (RexxActivation *t)
RexxActivation::run: call processTraps()
RexxActivation::processTraps(): entry
RexxActivation::processTraps(): i=0
RexxActivation::processClauseBoundary: entry
RexxActivation::processClauseBoundary: conditionQueue->isEmpty 1
COND: condition HALT raised on line 19, desc '', add 'The NIL object'
~~~


The trace for CALL ON HALT shows that the trap is not executed at all.
HALT is detected (though initially no RaiseCondition() is called),
processing is delayed until ClauseBoundary, trapping is confirmed, but
again, processing is delayed until ClauseBoundary (unexpected for me), and
finally the expected action (Rexx message) is not taken.

~~~
> TstBug1362-select call halt
Activity::halt: NULL
RexxActivation::halt: clauseBoundary = true
RexxActivation::processClauseBoundary: entry
RexxActivation::processClauseBoundary: conditionQueue == OREF_NULL
RexxActivation::processClauseBoundary: settings.haveHaltCondition()
Activity::raiseCondition: will be trapped
Activity::raiseCondition(DirectoryClass): calling trap()
RexxActivation::trap HALT checking exit
RexxActivation::trap isCall -> clauseBoundary = true
Activity::raiseCondition(DirectoryClass): (CALL ON - only) returning 1
RexxActivation::processClauseBoundary: raiseCondition(HALT)
returning
~~~


What *is* the expected trace flow for the SIGNAL ON HALT and the CALL ON
HALT path?  Are both paths broken?  Where do they go wrong?
Index: interpreter/concurrency/Activity.cpp
===================================================================
--- interpreter/concurrency/Activity.cpp	(revision 11255)
+++ interpreter/concurrency/Activity.cpp	(working copy)
@@ -552,8 +552,10 @@
     // creating this if we'll just end up throwing it away.
     if (!checkCondition(condition))
     {
+printf("Activity::raiseCondition: won't be trapped; return false\n");
         return false;
     }
+else printf("Activity::raiseCondition: will be trapped\n");
 
     // just create a condition object and process the traps.
     DirectoryClass *conditionObj = createConditionObject(condition, rc, description, additional, result);
@@ -613,6 +615,7 @@
     for (ActivationBase *activation = getTopStackFrame() ; !activation->isStackBase(); activation = activation->getPreviousStackFrame())
     {
         // see if there is an activation interested in trapping this.
+printf("Activity::raiseCondition(DirectoryClass): calling trap()\n");
         handled = activation->trap(condition, conditionObj);
         // for a normal condition, we stop checking at the first Rexx activation.
         if (handled || isOfClass(Activation, activation))
@@ -625,6 +628,7 @@
     // SIGNAL ON SYNTAX.  For CALL ON conditions, handled will be
     // true if a trap is pending.
 
+printf("Activity::raiseCondition(DirectoryClass): (CALL ON - only) returning %d\n", handled);
     return handled;
 }
 
@@ -2002,6 +2006,7 @@
     if (activation != NULL)
     {
         // please make it stop :-)
+printf("Activity::halt: %s\n", d == NULL ? "NULL" : d->getStringData());
         return activation->halt(d);
     }
     return true;
Index: interpreter/platform/windows/SystemCommands.cpp
===================================================================
--- interpreter/platform/windows/SystemCommands.cpp	(revision 11255)
+++ interpreter/platform/windows/SystemCommands.cpp	(working copy)
@@ -1,7 +1,7 @@
 /*----------------------------------------------------------------------------*/
 /*                                                                            */
 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.             */
-/* Copyright (c) 2005-2014 Rexx Language Association. All rights reserved.    */
+/* Copyright (c) 2005-2017 Rexx Language Association. All rights reserved.    */
 /*                                                                            */
 /* This program and the accompanying materials are made available under       */
 /* the terms of the Common Public License v1.0 which accompanies this         */
@@ -230,7 +230,11 @@
     siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
     titleChanged = GetConsoleTitle(ctitle, 255) != 0;
     siStartInfo.lpTitle = (LPSTR)cmdstring_ptr;
-    creationFlags = GetPriorityClass(GetCurrentProcess()) | CREATE_NEW_PROCESS_GROUP;
+    // if creation flag CREATE_NEW_PROCESS_GROUP is specified, CreateProcess() will
+    // implicitly call SetConsoleCtrlHandler(NULL,TRUE) which causes the created
+    // process to ignore Ctrl+C signals, as reported in [bugs:#1328]
+    // (for details see MSDN CreateProcess() and SetConsoleCtrlHandler())
+    creationFlags = GetPriorityClass(GetCurrentProcess()); // | CREATE_NEW_PROCESS_GROUP;
     if (!siStartInfo.hStdInput && !siStartInfo.hStdOutput && !titleChanged)  /* is REXXHIDE running without console */
     {
         if (!direct)
-- #1362 CALL ON ANY raises HALT too late and gives exception

parse arg signal error ctrlc

signal = signal~caselessStartsWith("s") -- SIGNAL, otherwise CALL
error = error~caselessStartsWith("e")   -- ERROR, otherwise HALT
ctrlc = ctrlc~caselessStartsWith("c")   -- Ctrl+C loop, otherwise "HI"

select
  when signal & error then signal on error
  when \signal & error then call on error
  when signal & \error then signal on halt
  when \signal & \error then call on halt
end

select
  when error then "exit 1"
  when \error & ctrlc then do 50e6; end
  when \error & \ctrlc then address "hostemu" "hi"    
end

say "returning"
return

any: halt: error:
say cond": condition" condition("C") "raised on line" sigl", desc '"condition("D")~string"', add '"condition("A")~string"'"
return

::requires hostemu library
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to