Possible Template Bug

I’ve been trying to track down the root cause of a “Maximum Recursion Depth Exceeded” error I’ve been seeing recently that triggers on a system.nav.swapTo() function call. I eventually narrowed it down to what appears to be a bug with how the dropdown component handles being disabled - via Security role settings - but only if the dropdown component is inside of a template.

If the security settings allow the dropdown to be enabled, everything is good. But when the security role is not allowed and disables the dropdown inside of a template, I get that recursion error. It typically doesn’t trigger the first time you navigate to the window, but it will trigger all subsequent attempts. (Note: The dropdown security settings work fine when the component is not inside of a template.)

My workaround for now is to just put a binding on the enabled property that checks for the proper roles. I will say that this was a particular nasty error since the recursion error always pointed to the swapTo function as being the culprit and depended on the role of the user…hopefully anyone else running into this error will see this and save a whole lot of headaches!

Running on:
Ignition 7.9.6 (b2018012914)
Java 8 u161 (same on server and client)
Gateway: Windows Server 2012
Client: MacOS 10.12.6

I’d keep digging. I’ve never seen Ignition itself trigger a recursion error – it’s always been a logic error where event scripts trigger each other under the given conditions. Put ‘print event’ at the beginning of every event script in that template (inside each if block of a propertyChange event) and look at the log just before your recursion exception.

The wording of the error makes it sound like it’s coming from Python too (if you google the error, you get mostly python results).

Python has a very limited stack (unlike Java which is just limited by the available memory AFAIK).

Do you have a stack trace to show where it’s coming from?

Related to that, Guido van Rossum also dislikes recursive functions, which is probably the reason of the limited stack size.

Part of the problem is conceptual: programmers forget (or never realized) that assigning to a component property in a script calls the component’s propertyChange event right there, which might then make another property assignment, recursing further and further. You don’t have to set up explicit functional recursion to get recursion in python/jython/java. (Or in any OO language with getter/setter hooks.)

pturmel - I was thinking the same thing you are, so I created a standalone test project that has just two windows in it and one template. Each window has one button with one line of code that calls the system.nav.swapTo() function to switch to the other window. One of the windows has an instance of the template and has the Security Role set so that the template will be disabled when I open the window from my username. The only thing inside the template is the default dropdown component. There is no additional scripting anywhere in the template or windows and since it is a project from scratch, I have no client/gateway scripts, etc. The recursive error still triggers on this bare bones project.

If you have any other thoughts or ideas for testing/debugging, let me know. Would be interested to know what the root cause of this is. If I have time, I’ll fire up my PC and see if I get the same error on there.

Below is the full error. Line 1 that it is referencing in the error is the system.nav.swapTo() function. Nothing unique in the script.

Traceback (most recent call last):
File “event:actionPerformed”, line 1, in
RuntimeError: maximum recursion depth exceeded

at org.python.core.Py.RuntimeError(Py.java:152)
at org.python.core.Py.JavaError(Py.java:490)
at org.python.core.Py.JavaError(Py.java:488)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188)
at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.__call__(ScriptManager.java:429)
at org.python.core.PyObject.__call__(PyObject.java:387)
at org.python.core.PyObject.__call__(PyObject.java:391)
at org.python.pycode._pyx7.f$0(<event:actionPerformed>:1)
at org.python.pycode._pyx7.call_function(<event:actionPerformed>)
at org.python.core.PyTableCode.call(PyTableCode.java:165)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1275)
at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:634)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:180)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:271)
at com.inductiveautomation.factorypmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:57)
at com.sun.proxy.$Proxy19.actionPerformed(Unknown Source)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2237)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2295)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4889)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4526)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4467)
at java.awt.Container.dispatchEventImpl(Container.java:2281)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Ignition v7.9.6 (b2018012914)
Java: Oracle Corporation 1.8.0_161

It’s a known bug that has been fixed in 7.9.7

2 Likes

Heh. I was about to say that the backtrace sure looks like an Ignition bug… (-:

Thanks Kathy! Just happy to know it wasn’t something I did!

Is there a forum topic or webpage anywhere that lists known bugs? I did quite a lot of searching when I was trying to debug this and couldn’t find anything about this issue.

No list of known bugs that you can access, but you can always see bugs that have been fixed in the change logs. The change log for 7.9.7 is at https://inductiveautomation.com/downloads/changelog/525

In general, you can go to the Early Access downloads page (https://inductiveautomation.com/downloads/beta) and get the latest change logs there.

1 Like