Don't abort the update checker thread when one curl_easy_perform fails.
[dcpomatic.git] / src / lib / update_checker.cc
index 52dfce7f782ce38ef8405f73fdf8337c90c94daa..3bc02b50af7a5116cebfdad1f854912fbfa908ed 100644 (file)
@@ -1,44 +1,50 @@
 /*
-    Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
 
-    This program is free software; you can redistribute it and/or modify
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    This program is distributed in the hope that it will be useful,
+    DCP-o-matic is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 
+
 #include "update_checker.h"
 #include "version.h"
-#include "safe_stringstream.h"
-#include "config.h"
 #include "util.h"
-#include "raw_convert.h"
+#include <dcp/raw_convert.h>
 #include <libcxml/cxml.h>
 #include <curl/curl.h>
 #include <boost/algorithm/string.hpp>
 #include <string>
+#include <iostream>
+
 
 #define BUFFER_SIZE 1024
 
+
 using std::cout;
 using std::min;
 using std::string;
 using std::vector;
 using boost::is_any_of;
 using boost::ends_with;
+using dcp::raw_convert;
+
 
 /** Singleton instance */
-UpdateChecker* UpdateChecker::_instance = 0;
+UpdateChecker* UpdateChecker::_instance = nullptr;
+
 
 static size_t
 write_callback_wrapper (void* data, size_t size, size_t nmemb, void* user)
@@ -46,22 +52,17 @@ write_callback_wrapper (void* data, size_t size, size_t nmemb, void* user)
        return reinterpret_cast<UpdateChecker*>(user)->write_callback (data, size, nmemb);
 }
 
+
 /** Construct an UpdateChecker.  This sets things up and starts a thread to
  *  do the work.
  */
 UpdateChecker::UpdateChecker ()
        : _buffer (new char[BUFFER_SIZE])
-       , _offset (0)
-       , _curl (0)
-       , _state (NOT_RUN)
-       , _emits (0)
-       , _thread (0)
-       , _to_do (0)
-       , _terminate (false)
+       , _state (State::NOT_RUN)
 {
        _curl = curl_easy_init ();
 
-       curl_easy_setopt (_curl, CURLOPT_URL, "http://dcpomatic.com/update");
+       curl_easy_setopt (_curl, CURLOPT_URL, "https://dcpomatic.com/update");
        curl_easy_setopt (_curl, CURLOPT_WRITEFUNCTION, write_callback_wrapper);
        curl_easy_setopt (_curl, CURLOPT_WRITEDATA, this);
        curl_easy_setopt (_curl, CURLOPT_TIMEOUT, 20);
@@ -70,29 +71,36 @@ UpdateChecker::UpdateChecker ()
        curl_easy_setopt (_curl, CURLOPT_USERAGENT, agent.c_str ());
 }
 
+
 void
 UpdateChecker::start ()
 {
-       _thread = new boost::thread (boost::bind (&UpdateChecker::thread, this));
+       _thread = boost::thread (boost::bind (&UpdateChecker::thread, this));
+#ifdef DCPOMATIC_LINUX
+       pthread_setname_np (_thread.native_handle(), "update-checker");
+#endif
 }
 
+
 UpdateChecker::~UpdateChecker ()
 {
+       boost::this_thread::disable_interruption dis;
+
        {
                boost::mutex::scoped_lock lm (_process_mutex);
                _terminate = true;
        }
 
        _condition.notify_all ();
-       if (_thread) {
-               _thread->join ();
-       }
-       delete _thread;
+       try {
+               _thread.join ();
+       } catch (...) {}
 
        curl_easy_cleanup (_curl);
        delete[] _buffer;
 }
 
+
 /** Start running the update check */
 void
 UpdateChecker::run ()
@@ -102,6 +110,7 @@ UpdateChecker::run ()
        _condition.notify_one ();
 }
 
+
 void
 UpdateChecker::thread ()
 {
@@ -126,8 +135,8 @@ UpdateChecker::thread ()
 
                        int r = curl_easy_perform (_curl);
                        if (r != CURLE_OK) {
-                               set_state (FAILED);
-                               return;
+                               set_state (State::FAILED);
+                               continue;
                        }
 
                        /* Parse the reply */
@@ -152,21 +161,22 @@ UpdateChecker::thread ()
                                _stable = stable;
                        }
 
-                       if (Config::instance()->check_for_test_updates() && version_less_than (dcpomatic_version, test)) {
+                       if (!test.empty() && version_less_than (dcpomatic_version, test)) {
                                _test = test;
                        }
 
                        if (_stable || _test) {
-                               set_state (YES);
+                               set_state (State::YES);
                        } else {
-                               set_state (NO);
+                               set_state (State::NO);
                        }
                } catch (...) {
-                       set_state (FAILED);
+                       set_state (State::FAILED);
                }
        }
 }
 
+
 size_t
 UpdateChecker::write_callback (void* data, size_t size, size_t nmemb)
 {
@@ -176,18 +186,19 @@ UpdateChecker::write_callback (void* data, size_t size, size_t nmemb)
        return t;
 }
 
+
 void
 UpdateChecker::set_state (State s)
 {
        {
                boost::mutex::scoped_lock lm (_data_mutex);
                _state = s;
-               _emits++;
        }
 
-       emit (boost::bind (boost::ref (StateChanged)));
+       emit (boost::bind(boost::ref(StateChanged)));
 }
 
+
 UpdateChecker *
 UpdateChecker::instance ()
 {
@@ -199,6 +210,7 @@ UpdateChecker::instance ()
        return _instance;
 }
 
+
 bool
 UpdateChecker::version_less_than (string const & a, string const & b)
 {
@@ -210,24 +222,24 @@ UpdateChecker::version_less_than (string const & a, string const & b)
        DCPOMATIC_ASSERT (ap.size() == 3 && bp.size() == 3);
 
        if (ap[0] != bp[0]) {
-               return raw_convert<int> (ap[0]) < raw_convert<int> (bp[0]);
+               return raw_convert<int>(ap[0]) < raw_convert<int>(bp[0]);
        }
 
        if (ap[1] != bp[1]) {
-               return raw_convert<int> (ap[1]) < raw_convert<int> (bp[1]);
+               return raw_convert<int>(ap[1]) < raw_convert<int>(bp[1]);
        }
        float am;
        if (ends_with (ap[2], "devel")) {
-               am = raw_convert<int> (ap[2].substr (0, ap[2].length() - 5)) + 0.5;
+               am = raw_convert<int>(ap[2].substr(0, ap[2].length() - 5)) + 0.5;
        } else {
-               am = raw_convert<int> (ap[2]);
+               am = raw_convert<int>(ap[2]);
        }
 
        float bm;
        if (ends_with (bp[2], "devel")) {
-               bm = raw_convert<int> (bp[2].substr (0, bp[2].length() - 5)) + 0.5;
+               bm = raw_convert<int>(bp[2].substr(0, bp[2].length() - 5)) + 0.5;
        } else {
-               bm = raw_convert<int> (bp[2]);
+               bm = raw_convert<int>(bp[2]);
        }
 
        return am < bm;