Deadlock between FocusExpireTask and ConferenceExpireTask in Jicofo

In jitsi-meet with reservations system,I found deadlock in FocusExpireTask & ConferenceExpireTask.

FocusExpireTask role is about to clear idle conference.
ConferenceExpireTask role is about to clear overtime conference.

After checked lastest code. I think the lock sequence of them could be a problem.

Lock sequence:

FocusExpireTask : conferencesSyncRoot -> RESTReservations object
ConferenceExpireTask : RESTReservations object-> conferencesSyncRoot

If there are some room expired while another room idle expire => system will be deadlock.

Log:

Found one Java-level deadlock:

“org.jitsi.utils.concurrent.RecurringRunnableExecutor.thread-org.jitsi.jicofo.health.Health”:
waiting to lock monitor 0x00007fc7780b4008 (object 0x00000007000787f8, a java.lang.Object),
which is held by “FocusExpireThread”
“FocusExpireThread”:
waiting to lock monitor 0x00007fc6980033f8 (object 0x00000007000782b0, a org.jitsi.impl.reservation.rest.RESTReservations),
which is held by “ConferenceDurationGuard”
“ConferenceDurationGuard”:
waiting to lock monitor 0x00007fc7780b4008 (object 0x00000007000787f8, a java.lang.Object),
which is held by “FocusExpireThread”

Java stack information for the threads listed above:

“org.jitsi.utils.concurrent.RecurringRunnableExecutor.thread-org.jitsi.jicofo.health.Health”:
at org.jitsi.jicofo.FocusManager.getConference(FocusManager.java:684)
- waiting to lock <0x00000007000787f8> (a java.lang.Object)
at org.jitsi.jicofo.health.Health.check(Health.java:197)
at org.jitsi.jicofo.health.Health.performCheck(Health.java:133)
at org.jitsi.health.AbstractHealthCheckService.run(AbstractHealthCheckService.kt:155)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.run(RecurringRunnableExecutor.java:216)
- locked <0x00000007006cbf60> (a java.util.LinkedList)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.runInThread(RecurringRunnableExecutor.java:292)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.access$000(RecurringRunnableExecutor.java:36)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor$1.run(RecurringRunnableExecutor.java:328)
“FocusExpireThread”:
at org.jitsi.impl.reservation.rest.RESTReservations.onFocusDestroyed(RESTReservations.java:313)
- waiting to lock <0x00000007000782b0> (a org.jitsi.impl.reservation.rest.RESTReservations)
at org.jitsi.jicofo.FocusManager.conferenceEnded(FocusManager.java:657)
- locked <0x00000007000787f8> (a java.lang.Object)
at org.jitsi.jicofo.JitsiMeetConferenceImpl.stop(JitsiMeetConferenceImpl.java:565)
- locked <0x0000000701323000> (a org.jitsi.jicofo.JitsiMeetConferenceImpl)
at org.jitsi.jicofo.FocusManager$FocusExpireThread.expireLoop(FocusManager.java:1055)
at org.jitsi.jicofo.FocusManager$FocusExpireThread$$Lambda$2/1551028144.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
“ConferenceDurationGuard”:
at org.jitsi.jicofo.FocusManager.destroyConference(FocusManager.java:618)
- waiting to lock <0x00000007000787f8> (a java.lang.Object)
at org.jitsi.impl.reservation.rest.RESTReservations$ConferenceExpireTask.run(RESTReservations.java:374)
- locked <0x00000007000782b0> (a org.jitsi.impl.reservation.rest.RESTReservations)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)

Found 1 deadlock.