Fix hang when encoding with GPU enabled but not working.
authorCarl Hetherington <cth@carlh.net>
Tue, 17 Dec 2024 23:17:05 +0000 (00:17 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 18 Dec 2024 09:51:44 +0000 (10:51 +0100)
src/lib/grok_j2k_encoder_thread.cc
src/lib/j2k_encoder.cc
test/j2k_encode_threading_test.cc

index 6975d9221bb601735e655d0e182374855f04fbc2..e6c256f11b6a19589bd78fd1893a0d0ca5e9c284 100644 (file)
@@ -67,6 +67,8 @@ try
                if (_context->launch(frame, grok.selected) && _context->scheduleCompress(frame)) {
                        frame_guard.cancel();
                }
+
+               boost::this_thread::interruption_point();
        }
 }
 catch (boost::thread_interrupted& e)
index b416f921d22d114fbdd4380a58be72e3181415e7..3aaaa4e766a49c3c747aec6f2cd07a187c0f28e2 100644 (file)
@@ -475,13 +475,19 @@ J2KEncoder::retry(DCPVideo video)
 {
 #ifdef DCPOMATIC_GROK
        {
-               boost::mutex::scoped_lock lock(_threads_mutex);
-               auto is_grok_thread_with_errors = [](shared_ptr<const J2KEncoderThread> thread) {
-                       auto grok = dynamic_pointer_cast<const GrokJ2KEncoderThread>(thread);
-                       return grok && grok->errors();
-               };
-
-               _give_up = std::any_of(_threads.begin(), _threads.end(), is_grok_thread_with_errors);
+               /* We might be destroying or remaking these threads, and hopefully in that case we'll come back here
+                * to check again; we definitely don't want to block in that case waiting to be allowed to check
+                * _threads.
+                */
+               boost::mutex::scoped_lock lock(_threads_mutex, boost::try_to_lock);
+               if (lock) {
+                       auto is_grok_thread_with_errors = [](shared_ptr<const J2KEncoderThread> thread) {
+                               auto grok = dynamic_pointer_cast<const GrokJ2KEncoderThread>(thread);
+                               return grok && grok->errors();
+                       };
+
+                       _give_up = std::any_of(_threads.begin(), _threads.end(), is_grok_thread_with_errors);
+               }
        }
 #endif
 
index 48a639faa65e26a77a38933a1ea8661b81797a57..58f354e8053dc50180dfaf558d16a979e4bfedd2 100644 (file)
@@ -25,6 +25,9 @@
 #include "lib/dcp_transcode_job.h"
 #include "lib/encode_server_description.h"
 #include "lib/film.h"
+#ifdef DCPOMATIC_GROK
+#include "lib/grok/context.h"
+#endif
 #include "lib/j2k_encoder.h"
 #include "lib/job_manager.h"
 #include "lib/make_dcp.h"
@@ -115,3 +118,31 @@ BOOST_AUTO_TEST_CASE(frames_not_lost_when_threads_disappear)
        BOOST_REQUIRE_EQUAL(dcp.cpls()[0]->reels()[0]->main_picture()->intrinsic_duration(), 423U);
 }
 
+
+#ifdef DCPOMATIC_GROK
+BOOST_AUTO_TEST_CASE(transcode_stops_when_gpu_enabled_with_no_gpu)
+{
+       ConfigRestorer cr;
+
+       grk_plugin::setMessengerLogger(new grk_plugin::GrokLogger("[GROK] "));
+
+       Config::Grok grok;
+       grok.enable = true;
+       Config::instance()->set_grok(grok);
+
+       auto content = content_factory(TestPaths::private_data() / "clapperboard.mp4");
+       auto film = new_test_film("transcode_stops_when_gpu_enabled_with_no_gpu", content);
+       film->write_metadata();
+       auto job = make_dcp(film, TranscodeJob::ChangedBehaviour::IGNORE);
+
+       int slept = 0;
+       while (JobManager::instance()->work_to_do() && slept < 10) {
+               dcpomatic_sleep_seconds(1);
+               ++slept;
+       }
+
+       BOOST_REQUIRE(slept < 10);
+
+       JobManager::drop();
+}
+#endif