Bug 215765 - libusb_handle_events_completed() hangs after device removal
Summary: libusb_handle_events_completed() hangs after device removal
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: usb (show other bugs)
Version: 11.0-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-usb (Nobody)
Depends on:
Reported: 2017-01-04 13:39 UTC by Konrad Jopek
Modified: 2017-01-04 14:21 UTC (History)
1 user (show)

See Also:

Logs from pcscd (22.74 KB, text/plain)
2017-01-04 13:39 UTC, Konrad Jopek
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Konrad Jopek 2017-01-04 13:39:36 UTC
Created attachment 178508 [details]
Logs from pcscd

pcscd installed on FreeBSD 11.0-CURRENT has serious problems when YubiKey was detached and reattached to machine. It looks like one of pcscd's threads hangs after device removal on function libusb_handle_events_completed() from libusb.

Steps to reproduce:
Install pcsc-lite either from ports or packages. Start pcscd demon in foreground mode with logging enabled:

pcscd -f -a -I

Try to attach YubiKey, list YubiKey status in GPG (gpg2 --card-status), detach it, reattach, list card status in GPG.
In my case the second attempt shows something like:

$ gpg2 --card-status
gpg: selecting openpgp failed: Operation not supported by device

while pcscd logs the following error:

02006441 ccid_usb.c:1323:InterruptStop() libusb_cancel_transfer failed: -5
14759547 winscard.c:261:SCardConnect() Reader Yubico Yubikey 4 OTP+U2F+CCID 00 00 Not Found

Expected result is that pcscd correctly reinitializes YubiKey and gpg shows correctly status of a YubiKey.

Also, there are questions from maintainer of pcscd and ccid related to libusb implementation in FreeBSD:

- Why libusb_handle_events_completed() does not return on device removal?
- How to cancel a transfer after device removal if libusb_cancel_transfer() fails with LIBUSB_ERROR_NOT_FOUND since the device is removed?

Please notice that on MacOS libusb_handle_events_completed() returns when the USB device is removed.

Here are the details about platform and installed software:
FreeBSD AMDC2690 11.0-RELEASE-p2 FreeBSD 11.0-RELEASE-p2 #0: Mon Oct 24 06:55:27 UTC 2016     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64

pcscd --version
pcsc-lite version 1.8.18.
Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.
Copyright (C) 2001-2015 by Ludovic Rousseau <ludovic.rousseau@free.fr>.
Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.
Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.
Enabled features: FreeBSD amd64-portbld-freebsd11.0 serial usb libusb usbdropdir=/usr/local/lib/pcsc/drivers/ ipcdir=/var/run/pcscd configdir=/usr/local/etc/reader.conf.d

ccid version is 1.4.25 patched to add more verbose logging.

Logs from verbose version of ccid are also attached to this mail.

Respects for Ludovico Rousseau for his help on debugging ccid and pcscd.
Comment 1 Hans Petter Selasky freebsd_committer 2017-01-04 13:57:05 UTC

Can you set the LIBUSB_DEBUG environment before running the USB application?

env LIBUSB_DEBUG=0 program > log0.txt
env LIBUSB_DEBUG=1 program > log1.txt
env LIBUSB_DEBUG=2 program > log2.txt

And reproduce the issue?

libusb_handle_events_completed() only returns when the *completed variable is set to non-zero, typically when the USB transfer callbacks receive a CANCELLED error code. Maybe the pcscd APP doesn't check for this error code?

Comment 2 Hans Petter Selasky freebsd_committer 2017-01-04 14:18:37 UTC

Also try to attach to the hung process using "gdb -p proc_number" and enter "bt" to get a backtrace. It will be helpful.

Comment 3 Hans Petter Selasky freebsd_committer 2017-01-04 14:21:58 UTC
Q: How to cancel a transfer after device removal if libusb_cancel_transfer() fails with LIBUSB_ERROR_NOT_FOUND since the device is removed?

A: The FreeBSD USB stack will automatically cancel all pending transfers belonging to a USB device when it is detached and upon receiving a transfer status of LIBUSB_TRANSFER_CANCELLED, pcscd should not try re-submit the USB transfer and set its termination flag.