summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2008-03-20 21:07:00 +0000
committerDaniel Drake <dsd@gentoo.org>2008-03-20 21:19:48 +0000
commit88884ae4bbe721dac117d5190303cb67852fa5d3 (patch)
tree5e24d5208e5010e09c8554dbff61b59ddee6131b
parentead09cde6895df0034a685516987ce253575e9a7 (diff)
downloadlibusb-88884ae4bbe721dac117d5190303cb67852fa5d3.tar.gz
Save transfer flags before invoking callback
The callback may free the transfer, in which case we can't read the flags after it has returned.
-rw-r--r--TODO1
-rw-r--r--libusb/io.c6
-rw-r--r--libusb/libusb.h5
3 files changed, 9 insertions, 3 deletions
diff --git a/TODO b/TODO
index 7282410..717bc8f 100644
--- a/TODO
+++ b/TODO
@@ -7,7 +7,6 @@ error codes
fixme review
review functionality missing over 0.1
endianness of control setup, issues when resubmitting transfers
-interpreting transfer flags after callback returns is not safe
rename poll to handle_events
make libusb_get_pollfds return const?
doxygen warnings
diff --git a/libusb/io.c b/libusb/io.c
index df5fe12..7900603 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -767,6 +767,7 @@ void usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
enum libusb_transfer_status status)
{
struct libusb_transfer *transfer = &itransfer->pub;
+ uint8_t flags;
if (status == LIBUSB_TRANSFER_SILENT_COMPLETION)
return;
@@ -782,11 +783,14 @@ void usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
}
}
+ flags = transfer->flags;
transfer->status = status;
transfer->actual_length = itransfer->transferred;
if (transfer->callback)
transfer->callback(transfer);
- if (transfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
+ /* transfer might have been freed by the above call, do not use from
+ * this point. */
+ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER)
libusb_free_transfer(transfer);
}
diff --git a/libusb/libusb.h b/libusb/libusb.h
index f326afc..a306af9 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -521,7 +521,10 @@ enum libusb_transfer_flags {
/** Automatically free() transfer buffer during libusb_free_transfer() */
LIBUSB_TRANSFER_FREE_BUFFER = 1<<1,
- /** Automatically call libusb_free_transfer() after callback returns */
+ /** Automatically call libusb_free_transfer() after callback returns.
+ * If this flag is set, it is illegal to call libusb_free_transfer()
+ * from your transfer callback, as this will result in a double-free
+ * when this flag is acted upon. */
LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2,
};