Mercurial > hg > orthanc
changeset 7163:5e8003d46cf5
fixed possible deadlock in ThreadedSetOfInstancesJob
| author | Alain Mazy <am@orthanc.team> |
|---|---|
| date | Tue, 29 Sep 2026 17:06:35 +0200 |
| parents | e72e3adae0cc |
| children | 22083f3fe932 |
| files | NEWS OrthancServer/Sources/ServerJobs/ThreadedSetOfInstancesJob.cpp |
| diffstat | 2 files changed, 28 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Tue Sep 29 16:25:10 2026 +0200 +++ b/NEWS Tue Sep 29 17:06:35 2026 +0200 @@ -32,6 +32,8 @@ (https://discourse.orthanc-server.org/t/find-worklist-with-localaet-from-modality-configuration/6482) * Added new warnings that can be disabled in the configuration: - W101_TruncatingDicomTagTo256Values +* Fixed a deadlock in Anonymization/Modification jobs: some instances failing to be processed + could keep the job in a "processing" state forever. * Fix use of the static runtime under Visual Studio (/MT), which broke in 1.12.10 * New CMake options: - "THIRD_PARTY_DOWNLOADS_ROOT_URL" to specify another webserver to downloads the third-parties from.
--- a/OrthancServer/Sources/ServerJobs/ThreadedSetOfInstancesJob.cpp Tue Sep 29 16:25:10 2026 +0200 +++ b/OrthancServer/Sources/ServerJobs/ThreadedSetOfInstancesJob.cpp Tue Sep 29 17:06:35 2026 +0200 @@ -46,11 +46,12 @@ namespace Orthanc { static const char* EXIT_WORKER_MESSAGE = "exit"; + static const unsigned int WORKER_DEQUEUE_TIMEOUT_MS = 100; - ThreadedSetOfInstancesJob::ThreadedSetOfInstancesJob(ServerContext& context, - bool hasPostProcessing, - bool keepSource, - size_t workersCount) : + ThreadedSetOfInstancesJob::ThreadedSetOfInstancesJob(ServerContext& context, + bool hasPostProcessing, + bool keepSource, + size_t workersCount) : hasPostProcessing_(hasPostProcessing), started_(false), stopRequested_(false), @@ -260,9 +261,27 @@ while (true) { - std::unique_ptr<SingleValueObject<std::string> > instanceId(dynamic_cast<SingleValueObject<std::string>*>(that->instancesToProcessQueue_.Dequeue(0))); - if (that->stopRequested_ // no lock(mutex) to access this variable, this is safe since it's just reading a boolean - || instanceId->GetValue() == EXIT_WORKER_MESSAGE) + std::unique_ptr<IDynamicObject> message(that->instancesToProcessQueue_.Dequeue(WORKER_DEQUEUE_TIMEOUT_MS)); + if (that->stopRequested_) // no lock(mutex) to access this variable, this is safe since it's just reading a boolean + { + return; + } + + if (message.get() == NULL) + { + continue; // timeout, nothing to process yet + } + + SingleValueObject<std::string>* instanceId = dynamic_cast<SingleValueObject<std::string>*>(message.get()); + if (instanceId == NULL) + { + LOG(ERROR) << "Unexpected message type in the instances queue"; + that->SetErrorCode(ErrorCode_InternalError); + that->StopWorkers(); + return; + } + + if (instanceId->GetValue() == EXIT_WORKER_MESSAGE) { return; }
