diff options
author | Alexander Pyhalov <apyhalov@gmail.com> | 2018-05-24 14:57:04 +0300 |
---|---|---|
committer | Nathan Hjelm <hjelmn@me.com> | 2019-04-04 22:36:14 -0600 |
commit | 133bbda6946fa4fdfdfcc879d6b0700cfec02e30 (patch) | |
tree | 59c878e87213e83313a01669d908a48c909baa25 | |
parent | 542e6fd03d115b74a9aa3ebea1d21d63e4a86aa1 (diff) | |
download | libusb-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.c | 20 | ||||
-rw-r--r-- | libusb/os/sunos_usb.c | 36 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |