diff options
author | Frank Li <Frank.Li@nxp.com> | 2019-01-11 13:09:51 -0600 |
---|---|---|
committer | Nathan Hjelm <hjelmn@me.com> | 2019-04-04 22:21:43 -0600 |
commit | fb864b7cde40695c094363ee97c370ae2acc2e68 (patch) | |
tree | 19221456711e0ea803bd822cbf535574cf716895 /libusb/io.c | |
parent | 85d1f361837bd719c433068a8f06d8d5c47d431f (diff) | |
download | libusb-fb864b7cde40695c094363ee97c370ae2acc2e68.tar.gz |
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 <Frank.Li@nxp.com>
Signed-off-by: Nathan Hjelm <hjelmn@me.com>
Diffstat (limited to 'libusb/io.c')
-rw-r--r-- | libusb/io.c | 2 |
1 files changed, 2 insertions, 0 deletions
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; } |