Save transfer flags before invoking callback
authorDaniel Drake <dsd@gentoo.org>
Thu, 20 Mar 2008 21:07:00 +0000 (21:07 +0000)
committerDaniel Drake <dsd@gentoo.org>
Thu, 20 Mar 2008 21:19:48 +0000 (21:19 +0000)
The callback may free the transfer, in which case we can't read the flags
after it has returned.

TODO
libusb/io.c
libusb/libusb.h

diff --git a/TODO b/TODO
index 7282410..717bc8f 100644 (file)
--- 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
index df5fe12..7900603 100644 (file)
@@ -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);
 }
 
index f326afc..a306af9 100644 (file)
@@ -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,
 };