-
Notifications
You must be signed in to change notification settings - Fork 47
Description
I get this error:
RecursionError: maximum recursion depth exceeded while calling a Python object
^CException ignored in atexit callback: <function _exit_function at 0x1555531fe9e0>
Traceback (most recent call last):
Gemini suggested the following fix. For what it's worth.
That traceback is incredibly telling. You hit a classic Python programming pitfall in the luna command-line tool.
While the command crashed on your screen, the good news is that the dhcpd service almost certainly restarted successfully in the background. The crash happened strictly within the CLI tool that was waiting to report the final status back to your terminal.
Here is the breakdown of the bug and how it should be fixed in the codebase.
The Bug: Uncontrolled Recursion in API Polling
When you ask the luna CLI to restart a service, it sends a command to the Luna daemon and then polls an API endpoint to check if the background job has finished.
Based on your stack trace, the problem lies in the /trinity/local/python/lib/python3.10/site-packages/luna/service.py file within the dig_service_status(uri) function.
The Flawed Logic: Instead of using a standard while loop to check the status, the developer wrote the function to call itself if the job is not yet complete (at line 127: return dig_service_status(uri)).
The Call Stack Overflow: Python does not support tail-call optimization. Every time the function checks the API and finds that the DHCP service is "still restarting," it adds a new frame to the call stack .
The Crash: Because restarting a service like DHCP can take a few seconds, and the script is polling the local REST API as fast as the CPU allows without a delay, it easily executes over 1,000 checks in a split second. This exceeds Python's hardcoded maximum recursion depth (RecursionError: maximum recursion depth exceeded), causing the CLI to instantly crash.
The Recommended Code Fix
To fix this permanently in the TrinityX GitHub repository, the dig_service_status function needs to be refactored from a recursive design to an iterative design with a small sleep interval to prevent hammering the API.
Here is the conceptual fix for luna/service.py:
Current Problematic Code (Recursive):
Python
def dig_service_status(self, uri):
result = Rest().get_raw(uri)
# If the task is still running, it calls itself endlessly
if result.get('status') == 'queued' or result.get('status') == 'running':
return self.dig_service_status(uri)
return result
Proposed Solution (Iterative):
Python
import time
def dig_service_status(self, uri):
while True:
result = Rest().get_raw(uri)
# Check if the task is finished
if result.get('status') not in ['queued', 'running']:
return result
# Wait 1 second before polling again to prevent CPU/API thrashing
time.sleep(1)
This iterative approach safely waits for the daemon to finish its work without blowing up the memory stack.
This is the full error text:
000019 12:27:16 [root@trinityc ~]# luna service dhcp restart
luna service dns restart
luna service luna2 restart
[========] 2026-03-12 17:27:24 :: queued service dhcp restart with queue_id 201
[========] 2026-03-12 17:27:24 :: restart service dhcp
Traceback (most recent call last):
File "/usr/bin/luna", line 7, in
CLI = Cli().main()
File "/trinity/local/python/lib/python3.10/site-packages/luna/cli.py", line 130, in main
self.call_class()
File "/trinity/local/python/lib/python3.10/site-packages/luna/cli.py", line 158, in call_class
call(self.args, self.parser, self.subparsers)
File "/trinity/local/python/lib/python3.10/site-packages/luna/service.py", line 53, in init
self.service_action()
File "/trinity/local/python/lib/python3.10/site-packages/luna/service.py", line 130, in service_action
response = dig_service_status(uri)
File "/trinity/local/python/lib/python3.10/site-packages/luna/service.py", line 127, in dig_service_status
return dig_service_status(uri)
File "/trinity/local/python/lib/python3.10/site-packages/luna/service.py", line 127, in dig_service_status
return dig_service_status(uri)
File "/trinity/local/python/lib/python3.10/site-packages/luna/service.py", line 127, in dig_service_status
return dig_service_status(uri)
[Previous line repeated 968 more times]
File "/trinity/local/python/lib/python3.10/site-packages/luna/service.py", line 112, in dig_service_status
result = Rest().get_raw(uri)
File "/trinity/local/python/lib/python3.10/site-packages/luna/utils/rest.py", line 382, in get_raw
response = self.session.get(
File "/trinity/local/python/lib/python3.10/site-packages/requests/sessions.py", line 600, in get
return self.request("GET", url, **kwargs)
File "/trinity/local/python/lib/python3.10/site-packages/requests/sessions.py", line 587, in request
resp = self.send(prep, **send_kwargs)
File "/trinity/local/python/lib/python3.10/site-packages/requests/sessions.py", line 701, in send
r = adapter.send(request, **kwargs)
File "/trinity/local/python/lib/python3.10/site-packages/requests/adapters.py", line 487, in send
resp = conn.urlopen(
File "/trinity/local/python/lib/python3.10/site-packages/urllib3/connectionpool.py", line 714, in urlopen
httplib_response = self._make_request(
File "/trinity/local/python/lib/python3.10/site-packages/urllib3/connectionpool.py", line 466, in _make_request
six.raise_from(e, None)
File "", line 3, in raise_from
File "/trinity/local/python/lib/python3.10/site-packages/urllib3/connectionpool.py", line 461, in _make_request
httplib_response = conn.getresponse()
File "/trinity/local/python/lib/python3.10/http/client.py", line 1375, in getresponse
response.begin()
File "/trinity/local/python/lib/python3.10/http/client.py", line 337, in begin
self.headers = self.msg = parse_headers(self.fp)
File "/trinity/local/python/lib/python3.10/http/client.py", line 236, in parse_headers
return email.parser.Parser(_class=_class).parsestr(hstring)
File "/trinity/local/python/lib/python3.10/email/parser.py", line 67, in parsestr
return self.parse(StringIO(text), headersonly=headersonly)
File "/trinity/local/python/lib/python3.10/email/parser.py", line 56, in parse
feedparser.feed(data)
File "/trinity/local/python/lib/python3.10/email/feedparser.py", line 176, in feed
self._call_parse()
File "/trinity/local/python/lib/python3.10/email/feedparser.py", line 180, in _call_parse
self._parse()
File "/trinity/local/python/lib/python3.10/email/feedparser.py", line 295, in _parsegen
if self._cur.get_content_maintype() == 'message':
File "/trinity/local/python/lib/python3.10/email/message.py", line 594, in get_content_maintype
ctype = self.get_content_type()
File "/trinity/local/python/lib/python3.10/email/message.py", line 578, in get_content_type
value = self.get('content-type', missing)
File "/trinity/local/python/lib/python3.10/email/message.py", line 471, in get
return self.policy.header_fetch_parse(k, v)
File "/trinity/local/python/lib/python3.10/email/_policybase.py", line 316, in header_fetch_parse
return self._sanitize_header(name, value)
File "/trinity/local/python/lib/python3.10/email/_policybase.py", line 287, in _sanitize_header
if _has_surrogates(value):
File "/trinity/local/python/lib/python3.10/email/utils.py", line 57, in _has_surrogates
s.encode()
RecursionError: maximum recursion depth exceeded while calling a Python object
[====== ] dhcp restart...t...