From: Hans de Goede <hdegoede@redhat.com>
To: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Linux Media Mailing List <linux-media@vger.kernel.org>
Subject: Re: [PATCH 3/6] v4l2-event: Remove pending events from fh event queue when unsubscribing
Date: Wed, 02 Nov 2011 10:14:20 +0100 [thread overview]
Message-ID: <4EB109EC.6000709@redhat.com> (raw)
Hi,
hverkuil wrote:
On Thursday, October 27, 2011 13:18:01 Hans de Goede wrote:
>> 1: There is no reason for this after v4l2_event_unsubscribe releases the
>> spinlock nothing is holding a reference to the sev anymore except for the
>> local reference in the v4l2_event_unsubscribe function.
>
> Not true. v4l2-ctrls.c may still have a reference to the sev through the
> ev_subs list in struct v4l2_ctrl. The send_event() function checks for a
> non-zero fh.
Ah, yes. You're right v4l2-ctrls.c may still hold a reference after
releasing the spinlock.
*But* setting sev->fh to NULL and checking for this in v4l2-ctrls: send_event(),
or doing something similar, is not only not needed it is outright wrong.
v4l2_event_unsubscribe() and v4l2-ctrls: send_event() don't hold any shared
lock, so any form of test then use in v4l2-ctrls: send_event() is inherent racy.
Here is the relevant code from v4l2-ctrls: send_event():
if (sev->fh && (sev->fh != fh ||
(sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
v4l2_event_queue_fh(sev->fh, &ev);
Now lets say that v4l2_event_unsubscribe and v4l2-ctrls: send_event() race
on the same sev, then the following could happens:
1) send_event checks sev->fh, finds it is not NULL
<thread switch>
2) v4l2_event_unsubscribe sets sev->fh NULL
3) v4l2_event_unsubscribe calls v4l2_ctrls del_event function, this blocks
as the thread calling send_event holds the ctrl_lock
<thread switch>
4) send_event calls v4l2_event_queue_fh(sev->fh, &ev) which not is equivalent
to calling: v4l2_event_queue_fh(NULL, &ev)
5) oops, NULL pointer deref.
Now again without setting sev->fh to NULL in v4l2_event_unsubscribe and
without the (now senseless since always true) sev->fh != NULL check in
send_event:
1) send_event is about to call v4l2_event_queue_fh(sev->fh, &ev)
<thread switch>
2) v4l2_event_unsubscribe removes sev->list from the fh->subscribed list
<thread switch>
3) send_event calls v4l2_event_queue_fh(sev->fh, &ev)
4) v4l2_event_queue_fh blocks on the fh_lock spinlock
<thread switch>
5) v4l2_event_unsubscribe unlocks the fh_lock spinlock
6) v4l2_event_unsubscribe calls v4l2_ctrls del_event function, this blocks
as the thread calling send_event holds the ctrl_lock
<thread switch>
8) v4l2_event_queue_fh takes the fh_lock
7) v4l2_event_queue_fh calls v4l2_event_subscribed, does not find it since
sev->list has been removed from fh->subscribed already -> does nothing
9) v4l2_event_queue_fh releases the fh_lock
10) the caller of send_event releases the ctrl lock (mutex)
<thread switch>
11) v4l2_ctrls del_event takes the ctrl lock
12) v4l2_ctrls del_event removes sev->node from the ev_subs list
13) v4l2_ctrls del_event releases the ctrl lock
14) v4l2_event_unsubscribe frees the sev, to which no references are being
held anymore
> All that is needed is to find some different way of letting send_event()
> know that this sev is no longer used. Perhaps by making sev->list empty?
Actually as explained above the fix is to not do any checks and let both
"subsystems" take care of their own locking / consistency without any
interactions (other then that v4l2_ctrls should not hold any references
to the sev after its del op has completed).
I'll update the patch to also remove the sev->fh check from v4l2_ctrls:
send_event() and update the commit message.
Regards,
Hans
next reply other threads:[~2011-11-02 9:13 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-02 9:14 Hans de Goede [this message]
-- strict thread matches above, loose matches on Subject: below --
2011-11-01 13:41 [PATCH 3/6] v4l2-event: Remove pending events from fh event queue when unsubscribing Hans de Goede
2011-10-31 15:16 Various ctrl and event frame work patches (version 2) Hans de Goede
2011-10-31 15:16 ` [PATCH 3/6] v4l2-event: Remove pending events from fh event queue when unsubscribing Hans de Goede
2011-11-02 10:00 ` Sakari Ailus
2011-10-27 11:17 Various ctrl and event frame work patches Hans de Goede
2011-10-27 11:18 ` [PATCH 3/6] v4l2-event: Remove pending events from fh event queue when unsubscribing Hans de Goede
2011-10-27 12:07 ` Laurent Pinchart
2011-10-30 10:24 ` Hans Verkuil
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4EB109EC.6000709@redhat.com \
--to=hdegoede@redhat.com \
--cc=hverkuil@xs4all.nl \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.