Hi there,
I am currently developing a USB/UVC camera and I think I discovered an
issue in the V4L2 event system. In userland I have implemented a thread
for the VIDIOC_DQEVENT ioctl, which blocks until there is a new event.
This works perfectly until the camera is disconnected during operation:
In v4l2_event_dequeue() the thread is put to sleep with
wait_event_interruptible(fh->wait, fh->navailable != 0)
and woken up only from __v4l2_event_queue_fh()
wake_up_all(&fh->wait);
So the event-dq-thread will only wake up when there is really a new
event queued. It will not wake up when the event is unsubscribed in
v4l2_event_unsubscribe() and it will also not wake up when
video_unregister_device() and and consequently v4l2_fh_exit() is called.
In userland, when the device is disconnected while streaming video,
VIDIOC_DQBUF and all other ioctls return with proper error codes, but
VIDIOC_DQEVENT blocks until doomsday.
The only (dirty) workaround I found is sending a signal to the userland
thread to force the wait_event_interruptible() to return.
I think this issue could be solved. I discovered that in videobuf2 a
similar issue is solved by checking the flag q->streaming in
wait_event_interruptible() in __vb2_wait_for_done_vb(). In
__vb2_queue_cancel() this flag is deasserted and all threads are woken
up with wake_up_all.
I suggest that the problem could be solved by waking the
event-dq-threads in v4l2_event_unsubscribe_all() or
v4l2_event_unsubscribe() so that v4l2_event_dequeue() can return.
Problem is that I have almost no experience in kernel development. Can
somebody with more knowledge in these matters please have a look at this
issue and confirm or correct my observations?
Best regards,
Michael