From fb864b7cde40695c094363ee97c370ae2acc2e68 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Fri, 11 Jan 2019 13:09:51 -0600 Subject: fix windows crash when multi-thread do sync transfer fun() { libusb_open() ... sync transfer libusb_close() } two thread call fun infininately. to speed up crash, enable application verifier below 20 cycle, assert(fd!=NULL) happen at check_pollfds below 100 cycle, crash at pollable_fd->overlappend in winusb_get_overlapped result with this fix, success fun over 1000 cycles in handle_events usbi_mutex_lock() fds = ctx->pollfds nfds = ctx->pollfds_cnt; usbi_mutex_unclock() usbi_poll() callback. usbi poll is not in mutex. pollfds may be change by usbi_add_pollfd and usbi_remove_pollfd. Although usbi_add_pollfd and usbi_remove_pollfd hold mutex, but usbi_poll and callback is not in protext of mutex. windows use fd as index of fb_table. fb_table may changed by usbi_remove_pollfd. the map between fd and internal file_descriptor may be wrong. this patch added ref count for file_descriptor, only free file_desciptor and remove it from fb_table when ref count is 0. ref count will be increase when fds copy with mutex lock. so fd always index validate file_descriptor. ref count will be descress before return from handle_events. the file_descriptor can be free safely at this time. Closes #521 Signed-off-by: Frank Li Signed-off-by: Nathan Hjelm --- libusb/io.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libusb/io.c') diff --git a/libusb/io.c b/libusb/io.c index 4c29046..1e9357c 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -2149,6 +2149,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) } fds = ctx->pollfds; nfds = ctx->pollfds_cnt; + usbi_inc_fds_ref(fds, nfds); usbi_mutex_unlock(&ctx->event_data_lock); timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); @@ -2281,6 +2282,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) done: usbi_end_event_handling(ctx); + usbi_dec_fds_ref(fds, nfds); return r; } -- cgit v1.2.1