Stop threads at the start of their object's destruction in all Job cases.
[dcpomatic.git] / src / lib / job.cc
index 8cc6ced8ef2e90f81f83d802466f269f8237eb59..a83249e798feba99abafc2a09f1393eb8cf5dc18 100644 (file)
@@ -46,11 +46,11 @@ using std::cout;
 using boost::shared_ptr;
 using boost::optional;
 using boost::function;
+using namespace dcpomatic;
 
 /** @param film Associated film, or 0 */
 Job::Job (shared_ptr<const Film> film)
        : _film (film)
-       , _thread (0)
        , _state (NEW)
        , _start_time (0)
        , _sub_start_time (0)
@@ -62,19 +62,25 @@ Job::Job (shared_ptr<const Film> film)
 
 Job::~Job ()
 {
-       if (_thread) {
-               _thread->interrupt ();
-               /* We can't use DCPOMATIC_ASSERT here as it may throw an exception */
-               if (_thread->joinable ()) {
-                       try {
-                               _thread->join ();
-                       } catch (...) {
-                               /* Too late to do anything about this */
-                       }
-               }
+#ifdef DCPOMATIC_DEBUG
+       /* Any subclass should have called stop_thread in its destructor */
+       assert (!_thread.joinable());
+#endif
+}
+
+void
+Job::stop_thread ()
+{
+       if (!_thread.joinable()) {
+               return;
        }
 
-       delete _thread;
+       _thread.interrupt ();
+       try {
+               _thread.join ();
+       } catch (...) {
+               /* Too late to do anything about this */
+       }
 }
 
 /** Start the job in a separate thread, returning immediately */
@@ -84,9 +90,9 @@ Job::start ()
        set_state (RUNNING);
        _start_time = time (0);
        _sub_start_time = time (0);
-       _thread = new boost::thread (boost::bind (&Job::run_wrapper, this));
+       _thread = boost::thread (boost::bind(&Job::run_wrapper, this));
 #ifdef DCPOMATIC_LINUX
-       pthread_setname_np (_thread->native_handle(), "job-wrapper");
+       pthread_setname_np (_thread.native_handle(), "job-wrapper");
 #endif
 }
 
@@ -172,12 +178,6 @@ Job::run_wrapper ()
                set_progress (1);
                set_state (FINISHED_ERROR);
 
-       } catch (dcp::MissingAssetError& e) {
-
-               set_error (e.message(), e.path().string());
-               set_progress (1);
-               set_state (FINISHED_ERROR);
-
        } catch (dcp::DCPReadError& e) {
 
                set_error (e.message(), e.detail().get_value_or(""));
@@ -190,6 +190,12 @@ Job::run_wrapper ()
                set_progress (1);
                set_state (FINISHED_ERROR);
 
+       } catch (FileError& e) {
+
+               set_error (e.what(), e.what());
+               set_progress (1);
+               set_state (FINISHED_ERROR);
+
        } catch (std::exception& e) {
 
                set_error (
@@ -507,7 +513,7 @@ Job::remaining_time () const
 void
 Job::cancel ()
 {
-       if (!_thread) {
+       if (!_thread.joinable()) {
                return;
        }
 
@@ -515,11 +521,8 @@ Job::cancel ()
                resume ();
        }
 
-       _thread->interrupt ();
-       DCPOMATIC_ASSERT (_thread->joinable ());
-       _thread->join ();
-       delete _thread;
-       _thread = 0;
+       _thread.interrupt ();
+       _thread.join ();
 }
 
 /** @return true if the job was paused, false if it was not running */