Bug 179 - orthanc-python: OnChangeCallgack not called when posting an instance from python
Summary: orthanc-python: OnChangeCallgack not called when posting an instance from python
Status: RESOLVED FIXED
Alias: None
Product: Orthanc
Classification: Unclassified
Component: Orthanc Core (show other bugs)
Version: unspecified
Hardware: All All
: --- normal
Assignee: Sébastien Jodogne
URL:
Depends on:
Blocks:
 
Reported: 2020-06-29 15:16 CEST by Sébastien Jodogne
Modified: 2020-06-29 15:27 CEST (History)
0 users

See Also:


Attachments
Orthanc-179.zip (8.09 KB, application/zip)
2020-06-29 15:17 CEST, Sébastien Jodogne
Details
1061855319-image.png (79.61 KB, image/png)
2020-06-29 15:27 CEST, Sébastien Jodogne
Details
2204091096-image.png (85.42 KB, image/png)
2020-06-29 15:27 CEST, Sébastien Jodogne
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sébastien Jodogne 2020-06-29 15:16:53 CEST
[BitBucket user: Alain Mazy]
[BitBucket date: 2020-05-15.14:36:40]

From: https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/orthanc-users/VBjqLziXA38/U-lTk_SsBgAJ

Start Orthanc with this python plugin:

```python
import orthanc
import json


def OnUpload(output, uri, **request):
    dicom_body = request["body"]
    print("Before post to /instances")
    orthanc_resp = orthanc.RestApiPost("/instances", dicom_body)
    print("After post to /instances")
    output.AnswerBuffer("Added", "application/json")


def OnChange(changeType, level, resourceId):
    if changeType == orthanc.ChangeType.STABLE_STUDY:
        print("Stable study from python: {}".format(resourceId))
    elif changeType == orthanc.ChangeType.NEW_INSTANCE:
        print("Instance stored from python: {}".format(resourceId))


# Comment this line back in, and the upload route will occasionally hang
orthanc.RegisterOnChangeCallback(OnChange)
orthanc.RegisterRestCallback("/upload", OnUpload)
```

Then, upload a file that is not already stored through the newly defined upload route:

`curl -X POST -H "Content-Type: application/d -u demo:demo --data-binary @CT000001.dcm localhost:8042/upload`

The `OnChange` callback is never called as seen in the log \(we would expect `Instance stored from python`: 

```
orthanc_1  | Before post to /instances
orthanc_1  | I0515 14:32:14.304934 PluginsManager.cpp:172] Calling Python global function: OrthancPluginRestApiPost()
orthanc_1  | I0515 14:32:14.304961 OrthancPlugins.cpp:2281] Plugin making REST POST call on URI /instances (built-in API)
orthanc_1  | I0515 14:32:14.305008 OrthancRestApi.cpp:116] Receiving a DICOM file of 222012 bytes through HTTP
orthanc_1  | I0515 14:32:14.307541 FilesystemStorage.cpp:118] Creating attachment "e4ac9d12-2f77-403e-9222-f7fb825b9bf1" of "DICOM" type (size: 1MB)
orthanc_1  | I0515 14:32:14.308555 FilesystemStorage.cpp:118] Creating attachment "fa5d92c1-5b96-4fc4-a35e-b30fa21aa6b7" of "JSON summary of DICOM" type (size: 1MB)
orthanc_1  | I0515 14:32:14.309717 ServerContext.cpp:428] New instance stored
```
Comment 1 Sébastien Jodogne 2020-06-29 15:17:04 CEST
Created attachment 20 [details]
Orthanc-179.zip
Comment 2 Sébastien Jodogne 2020-06-29 15:27:50 CEST
[BitBucket user: Sébastien Jodogne]
[BitBucket date: 2020-05-18.18:30:32]

Source thread on the forum: https://groups.google.com/d/msg/orthanc-users/VBjqLziXA38/U-lTk_SsBgAJ

Despite all my efforts, I wasn’t able to reproduce the issue. I see the expected “Stable study from python” message, about 1 minute after the upload \(which corresponds to the default “StableAge” that equals 60 seconds\). 

I also have not seen Orthanc hanging.

What is your version of Orthanc and of the Python plugin? What environment are you using?
Comment 3 Sébastien Jodogne 2020-06-29 15:27:51 CEST
[BitBucket user: Alain Mazy]
[BitBucket date: 2020-05-19.07:21:32]
Comment 4 Sébastien Jodogne 2020-06-29 15:27:51 CEST
[BitBucket user: Alain Mazy]
[BitBucket date: 2020-05-19.07:22:31]

@{sjodogne} I’ve added a zip file with a Docker setup to reproduce it.  Check test.sh for the steps.
Comment 5 Sébastien Jodogne 2020-06-29 15:27:52 CEST
[BitBucket user: Alain Mazy]
[BitBucket date: 2020-05-19.11:18:15]

Good news, I can reproduce it on my Windows dev machine.  It’s immediate with the “OverwriteInstances”: true and while uploading the file for the second time

`Thread 1: in rest handler for /upload` \(which is implemented in python \(-> PythonLock is locked\)\):

* while writing the instance in the index, the old patient is deleted → triggers a “PatientDeleted” change

`Thread 2: the ChangeThread:`

* locks the `listenersMutex_`because there is a change to handle
* a python listener must be triggered → waiting for PythonLock \(which is locked by Thread 1\)

`Thread 1: continues the rest handler `

* At some point, it needs to signal an “InstanceStored” event → needs to lock ``listenersMutex_` ``which is locked by thread 2 → deadlock



Thread1:

![](1061855319-image.png)
Thread 2:

![](2204091096-image.png)
Shouldn’t the ServerContext::Store push the “InstanceStored” event in a queue instead of signaling the listeners synchronously ?  

Looks like this can be done with `ServerContext::SignalChange`

I’ll check that …
Comment 6 Sébastien Jodogne 2020-06-29 15:27:54 CEST
Created attachment 111 [details]
1061855319-image.png
Comment 7 Sébastien Jodogne 2020-06-29 15:27:56 CEST
Created attachment 112 [details]
2204091096-image.png
Comment 8 Sébastien Jodogne 2020-06-29 15:27:57 CEST
[BitBucket user: Alain Mazy]
[BitBucket date: 2020-05-19.14:20:15]

fixed in https://hg.orthanc-server.com/orthanc/rev/cf6eb4fc6841

The fix will be available in Orthanc 1.7.0