Menu

#830 Deadlock between event subscription and callback

open
nobody
None
C++ API
5
2016-11-21
2016-11-21
No

I noticed that event subscriptions and event callbacks share a hidden lock, which can cause a deadlock in the following situation:

import time
import tango
import threading

CHANGE_EVENT = tango.EventType.CHANGE_EVENT

def callback(event):
    with monitor:
        print(event.attr_value.value)

monitor = threading.RLock()
with monitor:
    proxy = tango.DeviceProxy('sys/tg_test/1')
    eid1 = proxy.subscribe_event('double_scalar', CHANGE_EVENT, callback)
    time.sleep(1.)
    eid2 = proxy.subscribe_event('State', CHANGE_EVENT, callback)
    print('OK')
raw_input()

If an actual double_scalar event is generated during time.sleep, here's what happens:
- the callback thread acquires the hidden lock
- the callback thread waits for the monitor lock
- the main thread wakes up (end of sleep)
- the main thread runs subscribe_event
- the main thread waits for the hidden lock
- deadlock!

This is actually what happens in some devices, when the event callback tries to acquire the monitor lock (useful to prevent race condition between device callbacks and event callbacks).

Weirdly enough, I haven't been able to reproduce it during the first init_device. Instead, I had to run the INIT command to run init_device a second time and reliably generate the deadlock.

Tested with tango 9.2.2.

Discussion


Log in to post a comment.