提交 1dfa2812 编写于 作者: D Dmitry Torokhov

Input: reduce raciness when input handlers disconnect

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: NDmitry Torokhov <dtor@mail.ru>
上级 26be5a50
...@@ -700,9 +700,9 @@ static void evdev_disconnect(struct input_handle *handle) ...@@ -700,9 +700,9 @@ static void evdev_disconnect(struct input_handle *handle)
if (evdev->open) { if (evdev->open) {
input_flush_device(handle, NULL); input_flush_device(handle, NULL);
input_close_device(handle); input_close_device(handle);
wake_up_interruptible(&evdev->wait);
list_for_each_entry(client, &evdev->client_list, node) list_for_each_entry(client, &evdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&evdev->wait);
} else } else
evdev_free(evdev); evdev_free(evdev);
} }
......
...@@ -595,9 +595,9 @@ static void joydev_disconnect(struct input_handle *handle) ...@@ -595,9 +595,9 @@ static void joydev_disconnect(struct input_handle *handle)
if (joydev->open) { if (joydev->open) {
input_close_device(handle); input_close_device(handle);
wake_up_interruptible(&joydev->wait);
list_for_each_entry(client, &joydev->client_list, node) list_for_each_entry(client, &joydev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&joydev->wait);
} else } else
joydev_free(joydev); joydev_free(joydev);
} }
......
...@@ -767,9 +767,9 @@ static void mousedev_disconnect(struct input_handle *handle) ...@@ -767,9 +767,9 @@ static void mousedev_disconnect(struct input_handle *handle)
if (mousedev->open) { if (mousedev->open) {
input_close_device(handle); input_close_device(handle);
wake_up_interruptible(&mousedev->wait);
list_for_each_entry(client, &mousedev->client_list, node) list_for_each_entry(client, &mousedev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&mousedev->wait);
} else } else
mousedev_free(mousedev); mousedev_free(mousedev);
} }
......
...@@ -477,9 +477,9 @@ static void tsdev_disconnect(struct input_handle *handle) ...@@ -477,9 +477,9 @@ static void tsdev_disconnect(struct input_handle *handle)
if (tsdev->open) { if (tsdev->open) {
input_close_device(handle); input_close_device(handle);
wake_up_interruptible(&tsdev->wait);
list_for_each_entry(client, &tsdev->client_list, node) list_for_each_entry(client, &tsdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&tsdev->wait);
} else } else
tsdev_free(tsdev); tsdev_free(tsdev);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册