4

I'm trying to improve the portability of a C++ app by using boost:threads instead of our own wrapper over Win32 threads, and the issue of graceful thread termination (again) rears its ugly head.

On pure win32, I 'interrupt' threads by using QueueUserAPC to throw a "thread_interrupt" exception which causes all RAII objects to cleanup on the way out, as described here. Any 'alertable' OS function can be interrupted in this way, so things like mutex waits, sleeps, serial and socket I/O are all possible interruption points.

However, boost:mutexes etc. aren't "alertable" by QueueUserAPC on win32 - they call things like Sleep(n) rather then SleepEx(n, true))

Boost threads do have an "interrupt" mechanism (which similarly involves throwing an exception) but it seems to have the drawback that ONLY boost::thread calls are interruptable, so a third-party socket library (for example) cannot be interrupted.

What to do? I could modify the boost source locally to make it interruptable, but that feels like a poor choice and I don't think helps the portability. Redesigning the entire app to remove the requirement for graceful thread shutdown is a similarly unappealing route...

Community
  • 1
  • 1
Roddy
  • 66,617
  • 42
  • 165
  • 277
  • Just wondering, what do you mean with graceful shutdown? Because interupts are more like a last-resort very ugly kind of shutdown if you ask me. – KillianDS Jun 17 '10 at 21:29
  • @KillianDS - by graceful shutdown, I mean that objects get destructed properly on the way out. The boost 'interrupt' throws an exception to achieve this. Ungraceful shutdown doesn't destruct objects so will leak resources. – Roddy Jun 17 '10 at 22:01
  • Graceful interruption of third party libraries that don't provide an interface for this is impossible. – Basilevs Jun 18 '10 at 11:42
  • @Basilevs. Not true - I've had this working for years. See my answer to the 'linked' question. I know it may not work for all libraries, but it does work with many. – Roddy Jun 18 '10 at 14:00
  • In the linked question transactional DB provides such interface. (it supports abortion of client thread) – Basilevs Jun 19 '10 at 05:20

1 Answers1

1

I have an idea for a partial solution for Win32, but I have yet to test it:

My "thread interrupt" method could call both boost::thread.interrupt(), AND QueueUserAPC and The function invoked by QueueUserAPC would just call boost::interruption_point() to allow the boost interrupt to take control.

This should mean that the thread gets interrupted (but "differently") both when it's waiting on a boost synchronization object or an 'alertable' native windows one.

Roddy
  • 66,617
  • 42
  • 165
  • 277