git: 3b8c8b35de3a - main - evdev: Allow open() handler to be interrupted by a signal

Vladimir Kondratyev wulf at FreeBSD.org
Thu Jan 7 23:21:00 UTC 2021


The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=3b8c8b35de3a1a8a24169d144189b6a4db82ce10

commit 3b8c8b35de3a1a8a24169d144189b6a4db82ce10
Author:     Vladimir Kondratyev <wulf at FreeBSD.org>
AuthorDate: 2020-04-21 22:38:14 +0000
Commit:     Vladimir Kondratyev <wulf at FreeBSD.org>
CommitDate: 2021-01-07 23:18:42 +0000

    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)
---
 sys/dev/evdev/cdev.c          | 11 ++++++-----
 sys/dev/evdev/evdev_private.h |  9 +++++++++
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/sys/dev/evdev/cdev.c b/sys/dev/evdev/cdev.c
index c4550362ebce..ec60a12dbf2d 100644
--- a/sys/dev/evdev/cdev.c
+++ b/sys/dev/evdev/cdev.c
@@ -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);
 	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 */
-	EVDEV_LIST_LOCK(evdev);
 	if (dev->si_drv1 == NULL)
 		ret = ENODEV;
 	else
 		ret = evdev_register_client(evdev, client);
-
-	if (ret != 0)
-		evdev_revoke_client(client);
 	EVDEV_LIST_UNLOCK(evdev);
-
+out:
 	if (ret == 0)
 		ret = devfs_set_cdevpriv(client, evdev_dtor);
+	else
+		client->ec_revoked = true;
 
 	if (ret != 0) {
 		debugf(client, "cannot register evdev client");
diff --git a/sys/dev/evdev/evdev_private.h b/sys/dev/evdev/evdev_private.h
index 66a059c763bc..19636823b804 100644
--- a/sys/dev/evdev/evdev_private.h
+++ b/sys/dev/evdev/evdev_private.h
@@ -206,6 +206,15 @@ struct evdev_dev
 	else								\
 		sx_assert(&(evdev)->ev_list_lock, MA_OWNED);		\
 } 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
 {


More information about the dev-commits-src-all mailing list