summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Pyhalov <apyhalov@gmail.com>2018-05-24 14:57:04 +0300
committerNathan Hjelm <hjelmn@me.com>2019-04-04 22:36:14 -0600
commit133bbda6946fa4fdfdfcc879d6b0700cfec02e30 (patch)
tree59c878e87213e83313a01669d908a48c909baa25
parent542e6fd03d115b74a9aa3ebea1d21d63e4a86aa1 (diff)
downloadlibusb-133bbda6946fa4fdfdfcc879d6b0700cfec02e30.tar.gz
solaris: Fix crash on closing libusb handle
libusb_close() can interrupt transfer to device, setting dev_handle to NULL. In this case all async requests should exit gracefully. Also usbi_signal_transfer_completion() can dereference dev_handle in this case. Closes #434 Signed-off-by: Nathan Hjelm <hjelmn@me.com>
-rw-r--r--libusb/io.c20
-rw-r--r--libusb/os/sunos_usb.c36
-rw-r--r--libusb/version_nano.h2
3 files changed, 34 insertions, 24 deletions
diff --git a/libusb/io.c b/libusb/io.c
index 1e9357c..ef2b7c4 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1711,15 +1711,19 @@ int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer)
* function will be called the next time an event handler runs. */
void usbi_signal_transfer_completion(struct usbi_transfer *transfer)
{
- struct libusb_context *ctx = ITRANSFER_CTX(transfer);
- int pending_events;
+ libusb_device_handle *dev_handle = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->dev_handle;
- usbi_mutex_lock(&ctx->event_data_lock);
- pending_events = usbi_pending_events(ctx);
- list_add_tail(&transfer->completed_list, &ctx->completed_transfers);
- if (!pending_events)
- usbi_signal_event(ctx);
- usbi_mutex_unlock(&ctx->event_data_lock);
+ if (dev_handle) {
+ struct libusb_context *ctx = HANDLE_CTX(dev_handle);
+ int pending_events;
+
+ usbi_mutex_lock(&ctx->event_data_lock);
+ pending_events = usbi_pending_events(ctx);
+ list_add_tail(&transfer->completed_list, &ctx->completed_transfers);
+ if (!pending_events)
+ usbi_signal_event(ctx);
+ usbi_mutex_unlock(&ctx->event_data_lock);
+ }
}
/** \ingroup libusb_poll
diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c
index 05a5ef6..6a3f633 100644
--- a/libusb/os/sunos_usb.c
+++ b/libusb/os/sunos_usb.c
@@ -1196,26 +1196,32 @@ sunos_async_callback(union sigval arg)
int ret;
sunos_dev_handle_priv_t *hpriv;
uint8_t ep;
+ libusb_device_handle *dev_handle;
- hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv;
- ep = sunos_usb_ep_index(xfer->endpoint);
+ dev_handle = xfer->dev_handle;
- ret = aio_error(aiocb);
- if (ret != 0) {
- xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd);
- } else {
- xfer->actual_length =
- LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred =
- aio_return(aiocb);
- }
+ /* libusb can forcibly interrupt transfer in do_close() */
+ if (dev_handle != NULL) {
+ hpriv = (sunos_dev_handle_priv_t *)dev_handle->os_priv;
+ ep = sunos_usb_ep_index(xfer->endpoint);
+
+ ret = aio_error(aiocb);
+ if (ret != 0) {
+ xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd);
+ } else {
+ xfer->actual_length =
+ LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred =
+ aio_return(aiocb);
+ }
- usb_dump_data(xfer->buffer, xfer->actual_length);
+ usb_dump_data(xfer->buffer, xfer->actual_length);
- usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length,
- xfer->actual_length);
+ usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length,
+ xfer->actual_length);
- /* async notification */
- usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
+ /* async notification */
+ usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer));
+ }
}
static int
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index aefd792..e38dc22 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11359
+#define LIBUSB_NANO 11360