cachier: OSError: inotify instance limit reached
When using cachier with some long-running functions, I get the following error:
OSError: inotify instance limit reached
A fuller stack trace is in the details below. I have tried my best to obscure out proprietary information, so please forgive me if it kind of messes up the syntax.
What would be the best next step here to debug? (No pressure on your side, @shaypal5, I have no problems debugging on my own, just wanted to know your thoughts.)
--------------------------------------------------------------------------- OSError Traceback (most recent call last) <ipython-input-2-aff6f4218d64> in <module> ----> 1 s = my_long_func("arg")~/path/to/my/env/lib/python3.7/site-packages/cachier/core.py in func_wrapper(*args, **kwds) 169 return _calc_entry(core, key, func, args, kwds) 170 _print(‘No entry found. No current calc. Calling like a boss.’) –> 171 return _calc_entry(core, key, func, args, kwds) 172 173 def clear_cache():
~/path/to/my/env/lib/python3.7/site-packages/cachier/core.py in _calc_entry(core, key, func, args, kwds) 65 core.mark_entry_being_calculated(key) 66 # _get_executor().submit(core.mark_entry_being_calculated, key) —> 67 func_res = func(*args, **kwds) 68 core.set_entry(key, func_res) 69 # _get_executor().submit(core.set_entry, key, func_res)
~/path/to/my/src.py in my_long_func.py(kwarg, another_arg) 47 @cachier(stale_after=timedelta(weeks=1)) 48 def my_long_func.py(kwarg: str, another_arg: bool = False): —> 49 res_df = wrapped_func(kwarg=kwarg, another_arg=“string”) 50 if another_arg: 51 return res_df.query(“valid_data == True”)
~/path/to/my/env/lib/python3.7/site-packages/cachier/core.py in func_wrapper(*args, **kwds) 165 _print(‘No value but being calculated. Waiting.’) 166 try: –> 167 return core.wait_on_entry_calc(key) 168 except RecalculationNeeded: 169 return _calc_entry(core, key, func, args, kwds)
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 191 if observer.isAlive(): 192 # print(‘Timedout waiting. Starting again…’) –> 193 return self.wait_on_entry_calc(key) 194 # print(“Returned value: {}”.format(event_handler.value)) 195 return event_handler.value
~/path/to/my/env/lib/python3.7/site-packages/cachier/pickle_core.py in wait_on_entry_calc(self, key) 187 recursive=True 188 ) –> 189 observer.start() 190 observer.join(timeout=1.0) 191 if observer.isAlive():
~/path/to/my/env/lib/python3.7/site-packages/watchdog/observers/api.py in start(self) 253 def start(self): 254 for emitter in self._emitters: –> 255 emitter.start() 256 super(BaseObserver, self).start() 257
~/path/to/my/env/lib/python3.7/site-packages/watchdog/utils/init.py in start(self) 108 109 def start(self): –> 110 self.on_thread_start() 111 threading.Thread.start(self) 112
~/path/to/my/env/lib/python3.7/site-packages/watchdog/observers/inotify.py in on_thread_start(self) 119 def on_thread_start(self): 120 path = unicode_paths.encode(self.watch.path) –> 121 self._inotify = InotifyBuffer(path, self.watch.is_recursive) 122 123 def on_thread_stop(self):
~/path/to/my/env/lib/python3.7/site-packages/watchdog/observers/inotify_buffer.py in init(self, path, recursive) 33 BaseThread.init(self) 34 self._queue = DelayedQueue(self.delay) —> 35 self._inotify = Inotify(path, recursive) 36 self.start() 37
~/path/to/my/env/lib/python3.7/site-packages/watchdog/observers/inotify_c.py in init(self, path, recursive, event_mask) 186 inotify_fd = inotify_init() 187 if inotify_fd == -1: –> 188 Inotify._raise_error() 189 self._inotify_fd = inotify_fd 190 self._lock = threading.Lock()
~/path/to/my/env/lib/python3.7/site-packages/watchdog/observers/inotify_c.py in _raise_error() 413 raise OSError(“inotify watch limit reached”) 414 elif err == errno.EMFILE: –> 415 raise OSError(“inotify instance limit reached”) 416 else: 417 raise OSError(os.strerror(err))
</pre> </details>
About this issue
- Original URL
- State: open
- Created 4 years ago
- Comments: 29
@shaypal5 - I’m going to leave my analysis here for the moment (see
test2.py
comment with edit). It would be good if we could get some others to test this script check that it is reproducable on Linux systems (and does not trigger on non-linux systems).Edit: I’m pretty confident in my analysis now - see “Changing limits” in the previous comment.
Okay this time I can actually reproduce it.
Uses same
main.py
as above.test2.py
Running
Ran tests using
python3 main.py 1
Low count
High count
While running this test I checked how many instances were running (see above comment for SO link to where this snippet is from).
Running it again after it was done:
This matches what we’d expect of only being able to handle 88 more observers (88 + 40 == 128 (aka the limit)).
Running it again with exactly 88 observers: (note 88 is for my system while it is running while I write this, with my
max_user_instances
)Changing limits
Lets try changing the limits:
sudo sysctl fs.inotify.max_user_instances=200
If we now run the test again we should expect number of errors equal to number of already consumed instances (currently 40)
Analysis
Assuming this has correctly identified the issue:
This error only affects Linux using
inotify
(this will be majority of Linux users asinotify
requires Linux 2.6 which was first released in 2003).The error is triggered when a number of Cachier Pickle cores are waiting on a
"being_calculated"
value (which each create a newwatchdog.Observer
) which exhuasts the allowedinotify
instances available to a user (cat /proc/sys/fs/inotify/max_user_instances
). The exact number of waiting instances depends on themax_user_instances
and the number ofinotify
instances being consumed by other processes.Update:
I cannot reproduce the problem with the below scripts.
Why? It turns out I had a lot of hanging consumer threads that was probably taking me over the
max_user_instances
(cat /proc/sys/fs/inotify/max_user_instances
) which is probably being reported here (instead of my incorrect assumption above ofmax_user_watches
).(I identified this hanging threads usings the bash
find
snippet in https://unix.stackexchange.com/a/15549).Once I shutdown those consumer threads I could run the below tests with
70000
junk files which is well over my system’smax_user_watches
of65536
)Files
main.py
test.py
@shaypal5 - I suspect that the underlying issue has not been fixed as I’ve just hit this issue.
Edit: part of my hypothesis was wrong (is not to do with number of files in
cache_dir
)Details
Situation
Long running consumer completing same task (downloading image from URL), run across about 6000 tasks.
Using Cachier with Pickle core.
Versions
Traceback
Misc
Creating cached functions using the following:
Cache directory
OLD INCORRECT Analysis
Here’s what I think is happening and how it might be resolved.
First - there is a limit to how many files can be watched using inotofy (which is what
watchdog
is using with the Linux optimalObserver
). According to this page the defaultmax_user_watches
limit on most Linux systems is8192
- this is per user so includes anything else running.A workaround would be to increase this limit on the system being used, but this would just “postpone” the error.
Second - I believe that there are 2 scenarios that will trigger this limit being hit in general use.
a) cachier is being used across a large number of different functions b) a function is using
seperate_files=True
Third - the error is only thrown if a call to a cached function results in a
'being_calculated'
result - waiting for a result is the only time the observer is created . This observer watches the entire cache directory - so it doesn’t really matter which scenario fills the cache dir as long as the number of files is larger than the limit (in fact it might be possible that even filling the cache dir with non-cachier related files will trigger the error).For the fix I don’t think anything like “adding subdirectories per function” will help because of case
b)
above. It’s unclear ifwatchdog
Observer
s are designed to watch a single file (the current implementation is to watch the entirecache_dir
and filter on the expected file) - but this might be a solution. Some other work arounds would be to change what library we use for watching, or create a directory per key (kinda gross tbh), or simply create our own polling watcher (with a small sleep interval to avoid smashing the CPU - e.g.time.sleep(0.05) # 50ms
).I’ll see if I can find a way to reproduce the problem.
Oh, I forgot about your PR to fix this, @ericmjl . Please ping me again freely to make me take a look, but I suggest you two try to take a jab at this.