Linux: Fix race condition in cancel_bulk_transfer()
authorDavid Moore <dcm@acm.org>
Thu, 8 Jan 2009 06:31:09 +0000 (22:31 -0800)
committerDaniel Drake <dsd@gentoo.org>
Sat, 10 Jan 2009 16:35:57 +0000 (16:35 +0000)
commitd2a8ec2da8abcd8f4648ed118da16191011982dd
tree728c9317ea33594bf4d6321fe535f810fc40f4b7
parent34b9eebe35d8167d43cffb6ad6175f6b2251b572
Linux: Fix race condition in cancel_bulk_transfer()

This fixes a race condition in cancel_bulk_transfer().  In the old
version, awaiting_reap and awaiting_discard are incremented in
cancel_bulk_transfer() and decremented in handle_bulk_completion().
However, since these events may take place in two different threads,
these variables may reach zero before all URBs have been canceled,
triggered spurious callbacks and duplicate frees.

This changes the logic to use a single variable "num_retired" to replace
both awaiting_reap and awaiting_discard.  num_retired is incremented
only in handle_bulk_completion() and thus there is no race.  The handler
will know that all URBs have been canceled when num_retired becomes
equal to num_urbs.

This change also simplifies a great deal of the logic in both functions
and is a net reduction in the amount of code.

Note that some variables such as "reap_action" probably need to still be
protected by a mutex, and this patch does not address that issue.

Signed-off-by: David Moore <dcm@acm.org>
libusb/os/linux_usbfs.c