> On Oct 20, 2025, at 1:11 PM, Kirill Miazine <[email protected]> wrote:
> 
> 2025-10-20T21:45:53+0200 [pyng.master.PyngMaster#info] Unable to format event 
> {'check': <pyng.PING o
> bject at 0x294df13f3510>, 'log_logger': <Logger 'pyng.master.PyngMaster'>, 
> 'log_level': <LogLevel=in
> fo>, 'log_namespace': 'pyng.master.PyngMaster', 'log_source': 
> <pyng.master.PyngMaster object at 0x29
> 4df34c8090>, 'log_format': 'Ready to run {check.type} check "{check.desc}" 
> [{check.id <http://check.id/>}]', 'log_time'
> : 1760989553.4371765}: maximum recursion depth exceeded

My guess is that what's happening here is that because logging consumes several 
stack frames for the emitting, the formatting, etc, you're just getting unlucky 
and happening to blow your stack here as it's the biggest increase in the 
repeated function.  The message here is telling you that it can't format the 
message, but given that PyngCheck does not seem to have a dynamic __getattr__ 
or any @property descriptors, I don't think that that's where you're seeing the 
recursion.

The actual problem that I think you're seeing is just too large a number of 
Deferreds synchronously running their callbacks (which you can see via the 
addCallbacks on the top of the stack synchronously resulting in a _runCallbacks 
call. You're creating a Deferred for each go round the loop, without actually 
returning back up to the event loop at any point, eventually building up a huge 
stack of Deferred-calling-Deferred-calling-Deferred.  IIRC we have some 
mitigations for this to reduce the amount of recursion that Deferred does but 
it is not avoidable in the general case.

I suspect that the thing that you need here is just some backoff and jitter on 
some part of the retry here, rather than synchronously attempting to do things? 
I don't have time to fully absorb this logic but I can definitely see some 
mutual synchronous recursion between _get_check and _run_check, which is, I 
think, where you are running into problems (specifically with the implicit 
callback addition caused by returning a Deferred from _run_check into 
_get_check's addCallback).

Even if your stack is not meaningfully infinite, it's easy to get up around the 
stack limit if you just have a huge pile of Deferreds synchronously chain on to 
one another like this.  But even a deferLater(0) will break up the compounding 
callback stack and allow work to proceed.

-g
_______________________________________________
Twisted mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/twisted.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/RZKF6UB35BDCEHARQTRLRXPRMBS4ZPGR/
Code of Conduct: https://twisted.org/conduct

Reply via email to