I ran some tests and it seems a recursion results in infinite recursive calls that end with run time error.
Here's a sample selected log:
RuntimeError: maximum recursion depth exceeded^M
Traceback (most recent call last):^M
^M
File "/usr/local/lib/python2.7/dist-packages/oslo_messaging/rpc/server.py", line 155, in _process_incoming^M
res = self.dispatcher.dispatch(message)^M
^M
File "/usr/local/lib/python2.7/dist-packages/oslo_messaging/rpc/dispatcher.py", line 222, in dispatch^M
return self._do_dispatch(endpoint, method, ctxt, args)^M
^M
File "/usr/local/lib/python2.7/dist-packages/oslo_messaging/rpc/dispatcher.py", line 192, in _do_dispatch^M
result = func(ctxt, **new_args)^M
^M
File "/opt/stack/congress/congress/policy_engines/agnostic.py", line 22
20, in simulate^M
delta, trace, as_list)
File "/opt/stack/congress/congress/policy_engines/agnostic.py", line 820, in simulate^M
action_theory, delta, trace, as_list)^M
^M
File "/opt/stack/congress/congress/policy_engines/agnostic.py", line 1247, in _simulate_string^M
delta, trace)^M
^M
File "/opt/stack/congress/congress/policy_engines/agnostic.py", line 1296, in _simulate_obj^M
result = set(th_object.select(query))^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 129, in select^M
find_all=find_all)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 230, in top_down_evaluation^M
save=None)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 257, in top_down_abduction^M
self._top_down_eval(context, caller)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 332, in _top_down_eval^M
return self._top_down_truth(context, caller)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 435, in _top_down_truth^M
return self._top_down_includes(context, caller)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 439, in _top_down_includes^M
is_true = self._top_down_th(context, caller)^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 473, in _top_down_th^M
if self._top_down_eval(new_context, caller):^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 332, in _top_down_eval^M
return self._top_down_truth(context, caller)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 435, in _top_down_truth^M
return self._top_down_includes(context, caller)^M
^M
File "/opt/stack/congress/congress/datalog/topdown.py", line 439, in _top_down_includes^M
There are at least three options for addressing this error:
1. Perform static analysis of the query+policy rules to know ahead of time it'd lead to infinite recursive calls. Reject query.
2. Check the call stack to terminate infinite recursive call early.
3. Catch the RuntimeError when recursive call limit reached, then give a meaningful error message to user.
Given that the problem occurs infrequently, I think 3 is acceptable.
---
Note that there may be more complex variants of this problem. For example:
$ openstack congress policy rule create alpha 'a(x) :- b(x)'
+---------+--------------------------------------+
| Field | Value |
+---------+--------------------------------------+
| comment | |
| id | 36b90aee-a05a-45fd-9270-403289330f0d |
| name | None |
| rule | a(x) :- |
| | b(x) |
+---------+--------------------------------------+
user@ubuntu:~$ openstack congress policy simulate alpha 'b(x)' 'b+(x) :- a(x)' action
Internal server error (HTTP 500) (Request-ID: req-3714139c-ae7d-4767-8d70-93791905133f)
user@ubuntu:~$ openstack congress policy simulate alpha 'b(1)' 'b+(1) :- a(1)' action
Internal server error (HTTP 500) (Request-ID: req-d64b1fba-0840-461c-9d51-6a2d9095b723)
I ran some tests and it seems a recursion results in infinite recursive calls that end with run time error.
Here's a sample selected log: lib/python2. 7/dist- packages/ oslo_messaging/ rpc/server. py", line 155, in _process_incoming^M .dispatch( message) ^M lib/python2. 7/dist- packages/ oslo_messaging/ rpc/dispatcher. py", line 222, in dispatch^M dispatch( endpoint, method, ctxt, args)^M lib/python2. 7/dist- packages/ oslo_messaging/ rpc/dispatcher. py", line 192, in _do_dispatch^M congress/ congress/ policy_ engines/ agnostic. py", line 22 congress/ congress/ policy_ engines/ agnostic. py", line 820, in simulate^M congress/ congress/ policy_ engines/ agnostic. py", line 1247, in _simulate_string^M congress/ congress/ policy_ engines/ agnostic. py", line 1296, in _simulate_obj^M object. select( query)) ^M congress/ congress/ datalog/ topdown. py", line 129, in select^M all=find_ all)^M congress/ congress/ datalog/ topdown. py", line 230, in top_down_ evaluation^ M congress/ congress/ datalog/ topdown. py", line 257, in top_down_ abduction^ M _top_down_ eval(context, caller)^M congress/ congress/ datalog/ topdown. py", line 332, in _top_down_eval^M down_truth( context, caller)^M congress/ congress/ datalog/ topdown. py", line 435, in _top_down_truth^M down_includes( context, caller)^M congress/ congress/ datalog/ topdown. py", line 439, in _top_down_ includes^ M down_th( context, caller)^M congress/ congress/ datalog/ topdown. py", line 473, in _top_down_th^M down_eval( new_context, caller):^M congress/ congress/ datalog/ topdown. py", line 332, in _top_down_eval^M down_truth( context, caller)^M congress/ congress/ datalog/ topdown. py", line 435, in _top_down_truth^M down_includes( context, caller)^M congress/ congress/ datalog/ topdown. py", line 439, in _top_down_ includes^ M
RuntimeError: maximum recursion depth exceeded^M
Traceback (most recent call last):^M
^M
File "/usr/local/
res = self.dispatcher
^M
File "/usr/local/
return self._do_
^M
File "/usr/local/
result = func(ctxt, **new_args)^M
^M
File "/opt/stack/
20, in simulate^M
delta, trace, as_list)
File "/opt/stack/
action_theory, delta, trace, as_list)^M
^M
File "/opt/stack/
delta, trace)^M
^M
File "/opt/stack/
result = set(th_
^M
File "/opt/stack/
find_
^M
File "/opt/stack/
save=None)^M
^M
File "/opt/stack/
self.
^M
File "/opt/stack/
return self._top_
^M
File "/opt/stack/
return self._top_
^M
File "/opt/stack/
is_true = self._top_
File "/opt/stack/
if self._top_
^M
File "/opt/stack/
return self._top_
^M
File "/opt/stack/
return self._top_
^M
File "/opt/stack/
There are at least three options for addressing this error:
1. Perform static analysis of the query+policy rules to know ahead of time it'd lead to infinite recursive calls. Reject query.
2. Check the call stack to terminate infinite recursive call early.
3. Catch the RuntimeError when recursive call limit reached, then give a meaningful error message to user.
Given that the problem occurs infrequently, I think 3 is acceptable.
---
Note that there may be more complex variants of this problem. For example:
$ openstack congress policy rule create alpha 'a(x) :- b(x)' ---+--- ------- ------- ------- ------- ------- + ---+--- ------- ------- ------- ------- ------- + a05a-45fd- 9270-403289330f 0d | ---+--- ------- ------- ------- ------- ------- + ae7d-4767- 8d70-9379190513 3f) 0840-461c- 9d51-6a2d9095b7 23)
+------
| Field | Value |
+------
| comment | |
| id | 36b90aee-
| name | None |
| rule | a(x) :- |
| | b(x) |
+------
user@ubuntu:~$ openstack congress policy simulate alpha 'b(x)' 'b+(x) :- a(x)' action
Internal server error (HTTP 500) (Request-ID: req-3714139c-
user@ubuntu:~$ openstack congress policy simulate alpha 'b(1)' 'b+(1) :- a(1)' action
Internal server error (HTTP 500) (Request-ID: req-d64b1fba-