Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Threads, exceptions, and aborting

Moderators: larsivi kris

Posted: 11/14/08 16:33:18

I'm writing my very first multithreaded application. It's buggy. It throws exceptions.

When an exception is thrown in a thread other than the main one, the thread silently dies.

I've been running like this:

interface IThreadRunnable
{
   void run();
}
void run (IThreadRunnable runnable)
{
   (new Thread (&runnable.run)).start;
}

Now I'm running it like this:

interface IThreadRunnable
{
   void run();
}
class ThreadRunner
{
   IThreadRunnable runnable;
   void run ()
   {
      try
      {
          runnable.run;
      }
      catch (Exception ex)
      {
         log (ex);
         exit (1);
      }
   }
}
void run (IThreadRunnable runnable)
{
   (new Thread (&(new ThreadRunner(runnable)).run)).start;
}

This isn't very pretty. Is there a better way of doing this?

Author Message

Posted: 11/14/08 18:04:33

The ThreadRunner constructor to initialize the runnable is missing.

But this looks fine to me.

I see two other solutions:

  1. Make ThreadRunner a abstract class with a abstract "saveRun" method, that is overriden instead of the interface.
  2. Extend Thread to handle exception your way:
interface IThreadRunnable {
   void run();
}
class MyThread : Thread {
   private IThreadRunnable runnable;
   public this( IThreadRunnable runnable ){
      this.runnable = runnable;
      super(&run);
   }
   private final void run () {
      try {
          runnable.run;
      }
      catch (Exception ex) {
         log (ex);
         exit (1);
      }
   }
   public static MyThread start (IThreadRunnable runnable) {
      auto thread = new MyThread (&runnable.run);
      thread.start;
      return thread;
   }
}

Posted: 11/14/08 18:14:10

What you have is probably a good solution. If you want to catch exceptions when joining the threads, you can do that by passing 'true' to the Thread.join function.

I would get rid if IThreadRunnable and simplify ThreadRunner like this:

class ThreadRunner
{
  private void delegate() _r; 
  this(void delegate() r)
  {
      this._r = r;
      (new Thread(&_run)).start();
  }
  
  private void _run()
  {
    try
    {
      r();
    }
    catch(Exception ex)
    {
      log(ex);
      exit(1);
    }
  }
}

// to use
new ThreadRunner(&myobj.functionThatMightThrow);
// if you insist on having an IThreadRunnable interface:
IThreadRunnable itr;
new ThreadRunner(&itr.run);

Note that calling exit from within a worker thread can be considered poor programming practice. When I write multithreaded apps, I set a global variable indicating that all the threads should exit, and each thread checks the global variable periodically to see if it should exit, then cleans up all the resources it uses. Then the main thread calls join on all the sub-threads, and exits with an appropriate exit code.

Posted: 11/18/08 19:28:30

schveiguy wrote:

I would get rid if IThreadRunnable and simplify ThreadRunner like this:

I have IThreadRunnable so that my dependency injection container can start a new thread with a particular method whenever an object of this type is created.

schveiguy wrote:

Note that calling exit from within a worker thread can be considered poor programming practice. When I write multithreaded apps, I set a global variable indicating that all the threads should exit, and each thread checks the global variable periodically to see if it should exit, then cleans up all the resources it uses. Then the main thread calls join on all the sub-threads, and exits with an appropriate exit code.

During development, I want to fail immediately. It's okay for the operating system to do the cleanup for me for now. But thanks for the tip. Since most of my threads just have "while (true) {}", it should be easy enough to change over to a system like the one you recommend.