1

I have a problem with long running boost::regex_match(...) invocation in a threaded process environment. But it could be another lib (API call) having the same problem.

Is there a generic way to set up a watchdog for such?

For non-threaded process alarm() can be used to detect timeout. However, signals don't play nicely with threads. I can avoid direct use of alarm() in the thread and delegate timer mgt. to a dedicated separate thread and let that one use pthread_kill(...) to address the correct threads (this is just an idea - i didn't yet verify that part).

However, also this only interrupts and detects the situation, but cannot gracefully stop boost::regex_match(...). I played around with Throwing an exception from within a signal handler using sigsetjmp() and siglongjmp() for the thread using boost::regex_match(..). But it causes memory leaks in boost::regex_match(...) becausesiglongjmp()` bypasses destructors.

How can i gracefully stop a 3rd party API call - presuming that it's implemented exception safe?

Or does it have to be supported by some "stoppable" feature actively implemented in the 3rd party API? (is there some for the boost library?)

Maybe some strange idea, but:

Code can be implemented to be "thread-safe" and/or "exception-safe". Would it be an option to define "longjmp-safe"? This could be done by passing an additional token to a lib to let is associate all resource allocations to that token. After longjmp() the client SW could ask the API separately to release those resources.

simpler maybe would just be some central init()/release() or register()/unregister() API call, by which the API could clean-up itself.

Community
  • 1
  • 1
Frank Bergemann
  • 325
  • 2
  • 14
  • 2
    This cannot be done without the coöperation of the 3rd party library. Outside code cannot possibly determine, when it is safe to terminate the call, or what cleanup to perform (purging memory, releasing locks, closing connections, etc.). – IInspectable Sep 07 '16 at 07:42
  • Presume i have the option to terminate the thread after exception handling (with the sigsetjmp() and siglongjmp() way) and restart a new thread: How can i avoid the memory leaks? Can i switch the thread to use a private heap for memory allocations it does itself that will be cleaned up automatically for thread on exit? – Frank Bergemann Sep 07 '16 at 07:50
  • How do you release the locks? How do you close connections? This cannot work. – IInspectable Sep 07 '16 at 07:52
  • Even code compiled with exception support will have parts that can not handle exceptions, because compiler determined that there is no way exception would happen there and optimized them out. If you would somehow inject exception in there, bad things would happen. – michalsrb Sep 07 '16 at 08:36
  • You cannot gracefully stop a non-cooperating thread. – n. m. could be an AI Sep 07 '16 at 08:46
  • All this sounds like to fork() is the better option. Is there an option in between? Can i start a thread (pthread) and instruct it to take all non-inherited new allocated resources from the **private** heap, that is automatically cleaned up for thread-termination? – Frank Bergemann Sep 07 '16 at 18:50
  • All this sounds like to fork() is the better option - for long running "tasks". Maybe a thread/fork() mixed "task" model, which can quickly start new threads - if required - but replace old fork()'ed processes in case they have thread-garbage. – Frank Bergemann Sep 07 '16 at 18:59

1 Answers1

0

In a case where you have to:

  1. monitor exceeding execution time
  2. stop execution of processing

you should simply think for tasks instead of threads.

Using threads is something which sounds like "state of the art" but in practice tasks are very often the better way of implementation. Especially for controlling memory leeks in "undefined" end of execution, confine unwanted memory excess and control stack overruns etc.

In the case you have mentioned I tend to implement that as tasks. IPC works well on all known platforms but is not portable. If portability is no problem, changing to a task based solution is not a big deal.

A hanging task can be killed by a os call and all locks, memory and other resources like ipc/shared memory/pipes etc. will be removed automatically. So this fits much better to your problem and it did not depend on your external and maybe unchangeable third party components.

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • You still have (network) connections that aren't closed, files that are in an inconsistent state, because you bombed the task in the middle of writing to it, users, that haven't signed out of resources with exclusive access, etc. Less damage with respect to resource leaks, but still enough to not promote this as a solution. – IInspectable Sep 07 '16 at 13:37
  • @IInspectable: Sorry, but we are not talking of "any" resources but a known set of resources which are needed to encapsulate a functionality as given from the OP like call a `boost::regex_match(...)` and the needed IPC for that issue. In case if network ( sockets ) I believe that they will be handled correctly if the tasked is killed. And that files are maybe in a inconsistent state depends on the write and caching actions inside the process itself. So I disagree in many points you mention. – Klaus Sep 07 '16 at 13:41
  • `boost::regex_match` is the OP's immediate use-case. The question is still a more general one: *"How can i gracefully stop a 3rd party API call [...]?"* – IInspectable Sep 07 '16 at 13:47
  • @IInspectable: You are right: If you need "fits always" solution simply using a task instead of a thread did not work. This is why my answer contains: "you should simply think for tasks instead of threads" which indicates that this is a startpoint of your own solution finding process. It *can* be a step to a solution but it is not a must. And I did not write that it fits always. So it is a solution for a lot of use cases, not more not less. – Klaus Sep 07 '16 at 13:53
  • I've never heard anyone use "task" as a synonym for process. In languages I've stumbled over this it was more some amount of work that could be scheduled on one or more threads (c#, Java, cilk). Is this nomenclature common in some fields? – Voo Sep 08 '16 at 07:57