[
https://issues.apache.org/jira/browse/GUACAMOLE-2270?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Mike Jumper resolved GUACAMOLE-2270.
------------------------------------
Resolution: Fixed
> ABBA rwlock deadlock
> --------------------
>
> Key: GUACAMOLE-2270
> URL: https://issues.apache.org/jira/browse/GUACAMOLE-2270
> Project: Guacamole
> Issue Type: Bug
> Components: guacamole-server
> Affects Versions: 1.6.0
> Reporter: Masahji Stewart
> Priority: Major
> Fix For: 1.6.1 [staging]
>
>
> We've noticed an ABBA deadlock between two libguac functions that take
> {{display->last_frame.lock}} and {{display->pending_frame.lock}} in opposite
> orders:
> ||Function||Lock order||
> |{{guac_display_dup()}}|last_frame (R) -> pending_frame (R)|
> |{{guac_display_end_multiple_frames()}}|pending_frame (W) -> last_frame (W)|
> h2. How it happens
> When a new user is being promoted (the protocol's {{join_pending_handler}}
> calls {{{}guac_display_dup{}}}) at the same time the render loop is flushing
> a frame ({{{}guac_display_end_multiple_frames{}}}), the two threads wedge:
> * T1 holds {{last_frame.lock}} (R), blocks acquiring {{pending_frame.lock}}
> (R) — via {{guac_display_layer_get_bounds()}} called from inside
> {{{}guac_display_dup{}}}'s per-layer loop.
> * T2 holds {{pending_frame.lock}} (W), blocks acquiring {{last_frame.lock}}
> (W).
> The default Linux glibc rwlock policy queues new readers behind a waiting
> writer, so once T2 has parked on {{last_frame.lock}} as a writer, T1's
> pending read acquire never makes progress, and T2 cannot acquire
> {{last_frame.lock}} until T1 releases. Neither does.
> h2. Impact
> Once wedged, the entire display pipeline starves: the protocol-client thread
> (e.g. VNC) blocks on {{pending_frame.lock}} trying to mutate a layer;
> per-user add/remove paths block on the client-level users-rwlock. Viewers see
> a black screen — no draws flow for the rest of the connection.
> The race is intermittent and timing-dependent: it requires
> {{join_pending_handler}} firing while {{end_multiple_frames}} is past its
> {{defer_frame}} early-return and into the second lock acquire.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)