Input: reduce raciness when input handlers disconnect
authorDmitry Torokhov <dtor@insightbb.com>
Mon, 4 Jun 2007 03:29:36 +0000 (23:29 -0400)
committerDmitry Torokhov <dtor@insightbb.com>
Mon, 4 Jun 2007 03:50:05 +0000 (23:50 -0400)
There is a race between input handler's release() and disconnect()
methods: when input handler disconnects it wakes up all regular
users and then process to walk user list to wake up async. users.
While disconnect() walks the list release() removes elements of
the same list causing oopses.

While this is not a substibute for proper locking we can reduce
odds of getting an oops if we wake up normal readers after walking
the list.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/evdev.c
drivers/input/joydev.c
drivers/input/mousedev.c
drivers/input/tsdev.c

index a4c3729d39608d6f67f9a48547ab855407eef783..93b407cd46009ed895007d60284b94c6f34caaa8 100644 (file)
@@ -700,9 +700,9 @@ static void evdev_disconnect(struct input_handle *handle)
        if (evdev->open) {
                input_flush_device(handle, NULL);
                input_close_device(handle);
-               wake_up_interruptible(&evdev->wait);
                list_for_each_entry(client, &evdev->client_list, node)
                        kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+               wake_up_interruptible(&evdev->wait);
        } else
                evdev_free(evdev);
 }
index 9bcc5425049be22160039e6f6ad6073d126ff4d8..c83bfe8914ac8ecf2b42cad17da21f656a09d2e0 100644 (file)
@@ -595,9 +595,9 @@ static void joydev_disconnect(struct input_handle *handle)
 
        if (joydev->open) {
                input_close_device(handle);
-               wake_up_interruptible(&joydev->wait);
                list_for_each_entry(client, &joydev->client_list, node)
                        kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+               wake_up_interruptible(&joydev->wait);
        } else
                joydev_free(joydev);
 }
index 7678e987655022d7e9ab32d9e2db96ce6e16c081..dc78f62cbee16d1307aa3e0817ae9bfdac8d03cc 100644 (file)
@@ -767,9 +767,9 @@ static void mousedev_disconnect(struct input_handle *handle)
 
        if (mousedev->open) {
                input_close_device(handle);
-               wake_up_interruptible(&mousedev->wait);
                list_for_each_entry(client, &mousedev->client_list, node)
                        kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+               wake_up_interruptible(&mousedev->wait);
        } else
                mousedev_free(mousedev);
 }
index 5e5b5c91d75b1286451ff30b84ccf6985da12ff4..af4581d00d8202d4da205425c4add8bc17ec1c25 100644 (file)
@@ -477,9 +477,9 @@ static void tsdev_disconnect(struct input_handle *handle)
 
        if (tsdev->open) {
                input_close_device(handle);
-               wake_up_interruptible(&tsdev->wait);
                list_for_each_entry(client, &tsdev->client_list, node)
                        kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+               wake_up_interruptible(&tsdev->wait);
        } else
                tsdev_free(tsdev);
 }