[PATCH 3/4] utrace_set_events: fix UTRACE_EVENT(REAP) case
Oleg Nesterov
oleg at redhat.com
Tue Aug 17 11:55:34 UTC 2010
On 08/16, Roland McGrath wrote:
>
> > - It is possible that both ->death and ->reap are true. In this
> > case it is OK to clear UTRACE_EVENT(REAP), but set_events fails.
>
> No, it's not OK to clear it. Once ->reap is set, then the engine's
> ops->report_reap might or might not have been called already.
Afaics - no.
If utrace->death is set (and we check it under utrace->lock) we can
ignore utrace->reap.
In short, if ops->report_reap can be called before ->death is cleared,
then 2 possible callers of utrace_maybe_reap() can race with each other,
but this can't happen.
utrace->death == T means:
- (utrace_flags & _UTRACE_DEATH_EVENTS) == T
- utrace->death was set by utrace_report_death() which will take
utrace->lock later and clear ->death, only then it may call
ops->report_reap().
- until utrace_report_death() clears ->death, _UTRACE_DEATH_EVENTS
must be set in ->utrace_flags, otherwise utrace_maybe_reap(true)
is buggy.
Note that both utrace->death and _UTRACE_DEATH_EVENTS are cleared
"atomically" from utrace->lock pov.
IOW. utrace->death is true, then
IF (utrace->reap)
tracehook_prepare_releas()->utrace_maybe_reap(true) was
already called, this is how utrace->reap was set.
But utrace_maybe_reap() did nothing and returned.
We rely on the subsequent utrace_maybe_reap(false) from
utrace_report_death() - but this can't happen until
we drop utrace->lock
ELSE
utrace->reap can't be set until we drop utrace->lock.
Now that you merged c93fecc925ea7567168f0c94414b9021de2708c5
"get_utrace_lock() must not succeed if utrace->reap == T", this becomes
a bit off-topic. However, I thought about relaxing the "dead" check in
get_utrace_lock(), instead of utrace->reap we could check
"utrace->reap && !utrace->death". In fact, initially I was going to
do this, but then decided to make the simpler patch for now.
Oleg.
More information about the utrace-devel
mailing list