Skip to content

Commit

Permalink
drm: Avoid client deadlocks when the master disappears.
Browse files Browse the repository at this point in the history
This is done by
1) Wake up lock waiters when we close the master file descriptor.
   Not when the master structure is removed, since the latter
   requires the waiters themselves to release the refcount on the
   master structure -> Deadlock.
2) Send a SIGTERM to all clients waiting for the lock.
   Normally these clients will get a SIGPIPE when the X server dies,
   but clients may also spin trying to grab the DRM lock, without
   getting any sort of notification.

Signed-off-by: Thomas Hellstrom <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
  • Loading branch information
thomashvmw authored and airlied committed Mar 2, 2009
1 parent 171901d commit fda714c
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 8 deletions.
14 changes: 14 additions & 0 deletions drivers/gpu/drm/drm_fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,13 +484,27 @@ int drm_release(struct inode *inode, struct file *filp)
mutex_lock(&dev->struct_mutex);

if (file_priv->is_master) {
struct drm_master *master = file_priv->master;
struct drm_file *temp;
list_for_each_entry(temp, &dev->filelist, lhead) {
if ((temp->master == file_priv->master) &&
(temp != file_priv))
temp->authenticated = 0;
}

/**
* Since the master is disappearing, so is the
* possibility to lock.
*/

if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;
master->lock.hw_lock = NULL;
master->lock.file_priv = NULL;
wake_up_interruptible_all(&master->lock.lock_queue);
}

if (file_priv->minor->master == file_priv->master) {
/* drop the reference held my the minor */
drm_master_put(&file_priv->minor->master);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/drm_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
__set_current_state(TASK_INTERRUPTIBLE);
if (!master->lock.hw_lock) {
/* Device has been unregistered */
send_sig(SIGTERM, current, 0);
ret = -EINTR;
break;
}
Expand Down
8 changes: 0 additions & 8 deletions drivers/gpu/drm/drm_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,6 @@ static void drm_master_destroy(struct kref *kref)

drm_ht_remove(&master->magiclist);

if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;
master->lock.hw_lock = NULL;
master->lock.file_priv = NULL;
wake_up_interruptible_all(&master->lock.lock_queue);
}

drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
}

Expand Down

0 comments on commit fda714c

Please sign in to comment.