Page 1 of 1

Timeout for Misbehaving Function

PostPosted: Mon Aug 24, 2020 5:06 am
by DaveL17
I have a personal plugin that is at times misbehaving and going into an undead state. When I try to load the plugin config dialog, I get a beachball and eventually a

Code: Select all
runDialogForDevice() caught exception: NSInvalidArgumentException -- *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]
error. I think I've isolated the cause of the timeout to a single library that doesn't behave well and doesn't timeout.

I was looking for a way to wrap calls to this library in a

Code: Select all
with timeout(seconds=5):
call, but this only works on UNIX. In researching, I came across a lot of ideas that involve various approaches to using threads, multiprocessing queues and decorators. I like the look of using a timeout decorator best, but before opening up that Vietnam, wanted to check here if anyone has come across a timeout feature that runs well under Indigo plugin threading.

Re: Timeout for Misbehaving Function

PostPosted: Tue Aug 25, 2020 4:38 pm
by matt (support)
I don't have a recommendation for/against using a timeout decorator because of lack of experience, but just wanted to make a higher level comment that what you are seeing can occur when there is something that hangs the main server plugin, which includes all of the Indigo callbacks into the plugin (those always occur into the main thread). If the main thread is hung up on anything (network call, hardware, or this case a 3rd party library), then that might cause problems in the Indigo GUI (or Indigo Server) when it is trying to execute callbacks into the plugin for preparing, showing, or validating the UI (as well as executing actions and other callbacks).

The solution is what you've already surmised: to move anything that might hang or take a long time to process to a secondary thread. I'm not positive a timeout decorator will work, in that it appears to use signals for the timeout and the Indigo Plugin Host context under which plugins execute already has some signal overrides used by the Indigo Server ti shutdown/restart plugins. That said, it might work. :?

Re: Timeout for Misbehaving Function

PostPosted: Tue Aug 25, 2020 5:59 pm
by DaveL17
Thanks Matt. I liked the decorator approach because it seemed the most Pythonic.

Turns out that this is even more complicated than I thought. The 3rd party library in question is ipgetter (which has since been deprecated and removed from GitHub). But that's secondary to the issue. I believe that ipgetter tried to do its thing and sometimes got hung up and wouldn't release its block.

  • multiprocessing.process: ipgetter will run "properly" when run as an embedded script or linked script, but not in a multiprocessing process within a plugin (it will run in the plugin process--most of the time). While you can kill a process, this is moot because ipgetter won't run in a separate process within a plugin environment. Obviously, other things run just fine in separate processes, so it's something unique about ipgetter.
  • threading.thread: ipgetter will run "properly" in a separate thread, but truly killing a thread is non-trivial and probably requires some manner of the aforementioned signaling. In any event, based on my (limited) research, killing a thread is not recommended.
I ended up going a different way in order to drop the use of ipgetter itself, so I'm good on that front. But I still think the exercise of figuring out a robust and safe way to handle stuck 3rd party blocks would be popular.