Orthanc OnHeartBeat with exception when responding to itself?

Happy Thursday everyone! I’m having an interesting issue which I would like to share and hear back from anyone who’s experienced something similar.

I have an Orthanc (1.11.2) container in docker and a simple PHP application in another container. Both are on the same docker network.

I’ve created a test.php page (which makes a POST call, with Async turned on) to Orthanc which in turn, pulls a study from a remote peer - when I call that page from my browser, I get the immediate response I expect (JobID) and the job registers in Orthanc and the study downloads. Nice!

Wanting to automate this, I went further and used the Lua OnHeartBeat function to make the call to test.php … but I never seem to get a response back and eventually Orthanc crashes. We do see (in the logs) that the HttpClient shows the POST to /transfers/peer but then that’s it. It feels like (this time) it didn’t accept the “Asynchronous” : true that it was sent - and we’ve checked the PHP code. My lead developer and I have gone through hours of testing this.

We’ve even changed the test.php page to just try to get the /system response and it still fails. Calling the same page from postman or a browser works without fail.

We question whether or not, when OnHeartBeat makes a call, it sits until it receives a response and (more importantly) nothing else can happen on the Orthanc server until that OnHeartBeat gets a response.

Would / does that make any sense? I read that “This implies that Lua scripting in Orthanc does not support any kind of concurrency.” but I don’t believe that’s relevant in this case, as whilst the Lua script is making the OnHeartBeat call, the response to the API call happens on the CivetWeb level, doesn’t it?

Thoughts?

BNOEAFK

Hi Dave,

It’s quite a recurring issue and I just realized it was not properly documented. Hence the new text below that will appear in the Orthanc book in a few minutes.

For your particular use case, an alternative is that the OnHeartBeat callback includes the content of /system in the payload it sends to test.php

Best regards,

Alain

Concurrency and deadlocks

Orthanc only implements a single Lua context. Therefore, all these callbacks are guaranteed to be invoked in mutual exclusion. This implies that Lua scripting in Orthanc does not support any kind of concurrency but may also lead to some deadlocks.

If a lua function (e.g. OnHeartBeat) performs an HTTP call to an external Rest API (e.g. [http://myserver.com/orthanc_is_alive.php](http://myserver.com/orthanc_is_alive.php)) which, in turn, calls the Orthanc Rest API (e.g. call [http://orthanc:8042/system](http://orthanc:8042/system)), odds are high that you meet a deadlock because Orthanc, when handling a Rest API calls, may try to execute some Lua callbacks (e.g. IncomingHttpRequestFilter) while the Lua context is still blocked inside the OnHeartBeat function.

To avoid deadlocks, always make sure to avoid such back-and-forth communications or make sure they happen asynchronously: your webservice should call the Orthanc Rest API after it has returned from the endpoint called by OnHeartBeat.

Note that these deadlocks won’t happen when a lua function calls its own Orthanc Rest API using the RestApiGet, RestApiPost, … functions.