jbeard4 / SCION

SCXML/Statecharts in JavaScript, moved to gitlab: https://gitlab.com/scion-scxml/scion
https://scion.scxml.io
Apache License 2.0
149 stars 29 forks source link

provide interface or options allowing interpreter context to set execution limits #354

Open mattoshry opened 9 years ago

mattoshry commented 9 years ago

The purpose is to detect/prevent an FSM that has spun out of control.

Primary limits that come to mind:

Consider treating 'error' events (error, error.*) as special / single bucket with its own limit. Consider observing/limiting unhandled event count

Provide an interface to inform/notify the interpreter context when one of these limits has been exceeded so that the context can take appropriate action (e.g. terminate the session).

Here are a few bad scxml documents: 1) infinite raise 2) infinite send #_internal 3) infinite send #scxml

<scxml xmlns="http://www.w3.org/2005/07/scxml"
  version="1.0"
  initial="uber">

<datamodel>
  <data id="count" expr="0"/>
</datamodel>

<state id="uber">
  <transition event="loop" target="s1"/>

  <transition event="*">
    <log expr="'Ignoring unhandled input ' + JSON.stringify(_event)" label="TEST"/>
  </transition>

  <state id="s1">
    <onentry>
      <assign location="count" expr="count+1"/>
      <if cond="!count">
        <log expr="'Starting session ' + _sessionid" label="TEST"/>
      <else/>
        <log expr="'Re-entering s1 with count: ' + count" label="TEST"/>
      </if>
      <raise event="loop"/>
    </onentry>
  </state>
</state>
</scxml>

<scxml xmlns="http://www.w3.org/2005/07/scxml"
  version="1.0"
  initial="uber">

<datamodel>
  <data id="count" expr="0"/>
</datamodel>

<state id="uber">
  <transition event="loop" target="s1"/>

  <transition event="*">
    <log expr="'Ignoring unhandled input ' + JSON.stringify(_event)" label="TEST"/>
  </transition>

  <state id="s1">
    <onentry>
      <assign location="count" expr="count+1"/>
      <if cond="!count">
        <log expr="'Starting session ' + _sessionid" label="TEST"/>
      <else/>
        <log expr="'Re-entering s1 with count: ' + count" label="TEST"/>
      </if>
      <send target="#_internal" event="loop"/>
    </onentry>
  </state>
</state>

</scxml>

<scxml xmlns="http://www.w3.org/2005/07/scxml"
  version="1.0"
  initial="uber">

<datamodel>
  <data id="count" expr="0"/>
</datamodel>

<state id="uber">
  <transition event="loop" target="s1"/>

  <transition event="*">
    <log expr="'Ignoring unhandled input ' + JSON.stringify(_event)" label="TEST"/>
  </transition>

  <state id="s1">
    <onentry>
      <assign location="count" expr="count+1"/>
      <if cond="!count">
        <log expr="'Starting session ' + _sessionid" label="TEST"/>
      <else/>
        <log expr="'Re-entering s1 with count: ' + count" label="TEST"/>
      </if>
      <send type="http://www.w3.org/TR/scxml/#SCXMLEventProcessor"
          targetexpr="'#_scxml_' + _sessionid" event="loop"/>
    </onentry>
  </state>
</state>

</scxml>