recipriversexclusion
recipriversexclusion

Reputation: 15356

How to avoid hung processing in C++ through multithreading

In my code the main loop looks like the following

while ( (data = foo()) != NULL ) {
    // do processing on data here
}

where foo() is written in C (it fetches the next frame in a video stream, using libavcodec, if you're curious).

My problem is that due to reasons too complicated to go in here, sometimes foo() hangs, which stops the whole program. What I want to do is to detect this condition, i.e. foo() is taking more than N seconds and if this is so take action.

I thought of creating a separate thread to run foo() to implement this by I haven't done any multithreaded programming before. Here's what I want to do:

  1. Main thread creates a child thread and which calls foo()
  2. When foo() is done, the child thread returns
  3. Main thread processes data returned by foo()
  4. If the child takes more than a specified number of time an action is taken by the main thread.
  5. Steps 1-4 are repeated as long as foo() doesn't return null, which signals the end.

How do I go about doing this? Do I need three threads (main, to run foo() and for timing)?

Thanks!

Upvotes: 2

Views: 2475

Answers (5)

Anonym
Anonym

Reputation: 7715

How do I go about doing this?

You don't. The hard thing is that there is no reliable way to stop a thread - assuming the hang is in libavcodec, interrupting/killing a thread stuck in code you do not have control over leads to more problems than it solves(it might just be memory and file handle leaks if you're not too unlucky). The thread has to stop itself - but that's not an option if you're stuck inside libavcodec.

Many threading implementation doesn't let you kill threads either - though you might request that the thread cancels , if it's stuck in a infinite loop, it'll never cancel though as the cancel requests are processed only at certain boundary points in the OS or low level library calls.

To work around a buggy library like that in a reliable way, you need process isolation. What you do is create a separate program out of your foo() function, execute that and communicated with it using its stdin/stout streams - or some other form of IPC. Talking to an external program, you have various options for doing I/O with timeouts, and can kill the program when you determin it's hanging.

Upvotes: 4

Omnifarious
Omnifarious

Reputation: 56038

On Linux you can use pthread_timedjoin_np to make this happen with two threads really easily.

Upvotes: 1

Jay
Jay

Reputation: 14441

You'd probably be better off just fixing what ever is hanging your application.

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490048

This is exceedingly difficult to do well. The problem is what you're going to do when foo hangs. Nearly the only thing you can do at that point is abort the program (not just the thread) and start over -- killing the thread and attempting to re-start it might work, but it's dangerous at best. The OS will clean up resources when you kill a process, but not when you kill a single thread. It's essentially impossible to figure out what resources belong exclusively to that thread, and what might be shared with some other thread in the process.

That being the case, perhaps you could move the hanging-prone part to a separate process instead, and kill/restart that process when/if it hangs? You'd then send the data to the parent process via some normal form of IPC (e.g., a pipe). In this case, you could have two threads in the parent (processor and watchdog), or (if available) you could do some sort of asynchronous read with time out, and kill the child when/if the read times out (using only one thread).

Upvotes: 7

thorsten müller
thorsten müller

Reputation: 5651

I think you can do this with two threads and use the sleep() command in the main thread for the timing part as long as you don't need to do other work there.

Upvotes: 0

Related Questions