aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-07-19 10:52:18 +0200
committerHans de Goede <hdegoede@redhat.com>2013-07-30 17:21:20 +0200
commit3107f30baddabf18039a4ca99c8a50b7f13f4de8 (patch)
treeff64cebd1eaa5aeb66d319cfcf260bd4482293d1
parent9afce4282ecbb32e0cef9282d7f97f2353d7eca1 (diff)
downloadandroid_external_libusbx-3107f30baddabf18039a4ca99c8a50b7f13f4de8.tar.gz
android_external_libusbx-3107f30baddabf18039a4ca99c8a50b7f13f4de8.tar.bz2
android_external_libusbx-3107f30baddabf18039a4ca99c8a50b7f13f4de8.zip
linux_netlink: Remove use of pthread_cancel
Using pthread_cancel() presents the opportunity for deadlock, so use a control pipe to cause the event thread to gracefully exit. Inspired on the identical patch for linux_udev from Chris Dickens. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/os/linux_netlink.c58
-rw-r--r--libusb/version_nano.h2
2 files changed, 45 insertions, 15 deletions
diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c
index 913618c..758974f 100644
--- a/libusb/os/linux_netlink.c
+++ b/libusb/os/linux_netlink.c
@@ -56,6 +56,7 @@
#define KERNEL 1
static int linux_netlink_socket = -1;
+static int netlink_control_pipe[2] = { -1, -1 };
static pthread_t libusb_linux_event_thread;
static void *linux_netlink_event_thread_main(void *arg);
@@ -97,8 +98,17 @@ int linux_netlink_start_event_monitor(void)
/* TODO -- add authentication */
/* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */
+ ret = usbi_pipe(netlink_control_pipe);
+ if (ret) {
+ usbi_err(NULL, "could not create netlink control pipe");
+ close(linux_netlink_socket);
+ return LIBUSB_ERROR_OTHER;
+ }
+
ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
if (0 != ret) {
+ close(netlink_control_pipe[0]);
+ close(netlink_control_pipe[1]);
close(linux_netlink_socket);
return LIBUSB_ERROR_OTHER;
}
@@ -109,22 +119,30 @@ int linux_netlink_start_event_monitor(void)
int linux_netlink_stop_event_monitor(void)
{
int r;
+ char dummy = 1;
if (-1 == linux_netlink_socket) {
/* already closed. nothing to do */
return LIBUSB_SUCCESS;
}
- r = close(linux_netlink_socket);
- if (0 > r) {
- usbi_err(NULL, "error closing netlink socket. %s", strerror(errno));
- return LIBUSB_ERROR_OTHER;
+ /* Write some dummy data to the control pipe and
+ * wait for the thread to exit */
+ r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(NULL, "netlink control pipe signal failed");
}
+ pthread_join(libusb_linux_event_thread, NULL);
- pthread_cancel(libusb_linux_event_thread);
-
+ close(linux_netlink_socket);
linux_netlink_socket = -1;
+ /* close and reset control pipe */
+ close(netlink_control_pipe[0]);
+ close(netlink_control_pipe[1]);
+ netlink_control_pipe[0] = -1;
+ netlink_control_pipe[1] = -1;
+
return LIBUSB_SUCCESS;
}
@@ -253,20 +271,32 @@ static int linux_netlink_read_message(void)
static void *linux_netlink_event_thread_main(void *arg)
{
- struct pollfd fds = {.fd = linux_netlink_socket,
- .events = POLLIN};
+ char dummy;
+ int r;
+ struct pollfd fds[] = {
+ { .fd = netlink_control_pipe[0],
+ .events = POLLIN },
+ { .fd = linux_netlink_socket,
+ .events = POLLIN },
+ };
/* silence compiler warning */
(void) arg;
- while (1 == poll(&fds, 1, -1)) {
- if (POLLIN != fds.revents) {
+ while (poll(fds, 2, -1) >= 0) {
+ if (fds[0].revents & POLLIN) {
+ /* activity on control pipe, read the byte and exit */
+ r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
+ if (r <= 0) {
+ usbi_warn(NULL, "netlink control pipe read failed");
+ }
break;
}
-
- usbi_mutex_static_lock(&linux_hotplug_lock);
- linux_netlink_read_message();
- usbi_mutex_static_unlock(&linux_hotplug_lock);
+ if (fds[1].revents & POLLIN) {
+ usbi_mutex_static_lock(&linux_hotplug_lock);
+ linux_netlink_read_message();
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
+ }
}
return NULL;
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index f875265..06ffd46 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10784
+#define LIBUSB_NANO 10785