evdev: Allow open() handler to be interrupted by a signal
It is possible that the client list lock is taken by other process for too long due to e.g. IO timeouts. Allow user to terminate open() in this case. Reviewed by: markj (as part of D27865)
This commit is contained in:
parent
d276eae674
commit
3b8c8b35de
@ -126,19 +126,20 @@ evdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
|||||||
mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF);
|
mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF);
|
||||||
knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx);
|
knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx);
|
||||||
|
|
||||||
|
ret = EVDEV_LIST_LOCK_SIG(evdev);
|
||||||
|
if (ret != 0)
|
||||||
|
goto out;
|
||||||
/* Avoid race with evdev_unregister */
|
/* Avoid race with evdev_unregister */
|
||||||
EVDEV_LIST_LOCK(evdev);
|
|
||||||
if (dev->si_drv1 == NULL)
|
if (dev->si_drv1 == NULL)
|
||||||
ret = ENODEV;
|
ret = ENODEV;
|
||||||
else
|
else
|
||||||
ret = evdev_register_client(evdev, client);
|
ret = evdev_register_client(evdev, client);
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
evdev_revoke_client(client);
|
|
||||||
EVDEV_LIST_UNLOCK(evdev);
|
EVDEV_LIST_UNLOCK(evdev);
|
||||||
|
out:
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = devfs_set_cdevpriv(client, evdev_dtor);
|
ret = devfs_set_cdevpriv(client, evdev_dtor);
|
||||||
|
else
|
||||||
|
client->ec_revoked = true;
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
debugf(client, "cannot register evdev client");
|
debugf(client, "cannot register evdev client");
|
||||||
|
@ -206,6 +206,15 @@ struct evdev_dev
|
|||||||
else \
|
else \
|
||||||
sx_assert(&(evdev)->ev_list_lock, MA_OWNED); \
|
sx_assert(&(evdev)->ev_list_lock, MA_OWNED); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
static inline int
|
||||||
|
EVDEV_LIST_LOCK_SIG(struct evdev_dev *evdev)
|
||||||
|
{
|
||||||
|
if (evdev->ev_lock_type == EV_LOCK_MTX) {
|
||||||
|
EVDEV_LOCK(evdev);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (sx_xlock_sig(&evdev->ev_list_lock));
|
||||||
|
}
|
||||||
|
|
||||||
struct evdev_client
|
struct evdev_client
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user