rx: Return success value when cancelling an event
authorSimon Wilkinson <sxw@your-file-system.com>
Thu, 22 Nov 2012 08:41:51 +0000 (08:41 +0000)
committerJeffrey Altman <jaltman@your-file-system.com>
Sat, 1 Dec 2012 17:51:20 +0000 (09:51 -0800)
commitf40199327a8753d8350b5fefedc2bb556b8b00a6
treeb357e64b4210903f029e3ed43603a29603c30500
parent20034a815750beff262d49b37fba225c72dd0ab1
rx: Return success value when cancelling an event

When cancelling an event that holds reference counts, we need
to know whether the attempt to cancel the event was successful
or not, otherwise references can be double put when the
cancellation races with the event firing. Take the follwing

Thread A Event Thread
========= ============

... event fired ...
MUTEX_ENTER(&obj->lock);
if (obj->event) {
    rxevent_Cancel(&obj->event);
    obj_put(&obj->refcnt);
}
MUTEX_EXIT(&obj->lock)
MUTEX_ENTER(&obj->lock);
if (event == obj->event)
    rxevent_Put(&obj->event);
...
MUTEX_EXIT(&obj->lock);
obj_put(&obj->refcnt);

Holding obj->lock doesn't control whether the event is fired or
not. Only putting the reference if the event being fired matches
that in obj doesn't help - it just leaks a reference in a different
race.

So, make rxevent_Cancel return true if it did actually cancel the
event, and false if the event has already been fired. This means
that Thread A can become

MUTEX_ENTER(&obj->lock);
if (rxevent_Cancel(&obj->event)
    obj_put(&obj->refcnt);
MUTEX_EXIT(&obj->lock)

In the example above, rxevent_Cancel would return false.

Change-Id: I48e012774c97c9d9588b00687428a32795be2b37
Reviewed-on: http://gerrit.openafs.org/8539
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
src/rx/rx_event.c
src/rx/rx_event.h
src/rx/rx_prototypes.h