[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#791766: /usr/lib/cups/backend-available/usb: USB backend eats 100% CPU



Am Donnerstag, den 09.07.2015, 14:11 +0100 schrieb Brian Potkin:
> The word "sometimes" isn't one which brings joy to the heart when bug
> hunting. :)

Yes, I know, sorry. It is also confusing for me. As I wrote in one of
my later follow-ups, if I "killall -9 usb" the backend, the next
printing attempt may work without a flaw. thus, I suspect something
like a race condition as the culprit.

> How ofter does this happen? Has it just appeared with cups 2.0.3?

No, it also happened with cups 1.x. I just didn't find the time and
nerves to report the bug, because - just as you said - "it sometimes
dosn't work" isn't a good bug description to start with. ;)

> > ioctl(15, USBDEVFS_CLAIMINTERFACE, 0x7fffad353bfc) = -1 EBUSY 
> > (Device or resource busy)

I believe that the code which causes this is the following in
backend/usb-libusb.c:1515:

  while ((errcode = libusb_claim_interface(printer->handle, number1)) < 0)
  {
    if (errcode != LIBUSB_ERROR_BUSY)
    {
      fprintf(stderr,
              "DEBUG: Failed to claim interface %d for %04x:%04x: %s\n",
              number1, devdesc.idVendor, devdesc.idProduct, strerror(errno));

      goto error;
    }
  }

So, what it does is trying to claim the interface and if the error code
isn't LIBUSB_ERROR_BUSY it busts out. But what if the error code
actually is LIBUSB_ERROR_BUSY? then the code is dead-locked in this
loop and tries to claim the interface endlessly. I think this is what I
see on my system.

Well, it's not that easy. Actually, LIBUSB_ERROR_BUSY is only returned
if the USB interface is already claimed, e.g. by a kernel driver. This
is checked earlier in the code in line 1437: If the return value of
libusb_kernel_driver_active() is 1 then a kernel driver is active and 
libusb_detach_kernel_driver() is called. So, it should be impossible
for the interface to be already claimed when the code in line 1515 is
called. But, one never knows, and repeatedly calling
libusb_claim_interface() over and over again won't help if the culprit
is LIBUSB_ERROR_BUSY but this is never checked for.

Thus, I assume that the following patch might work, but i am not sure
yet, because, you know, it only happens "sometimes". ;)

--- a/cups-2.0.3/backend/usb-libusb.c
+++ b/home/greffrath/usb-libusb.c
@@ -1522,6 +1522,16 @@ open_device(usb_printer_t *printer,      /* I - Printer */
 
       goto error;
     }
+    else if ((errcode = libusb_detach_kernel_driver(printer->handle, printer->iface)) < 0)
+    {
+      fprintf(stderr,
+              "DEBUG: Failed to detach \"usblp\" module from %04x:%04x\n",
+              devdesc.idVendor, devdesc.idProduct);
+
+      goto error;
+    }
+
+    sleep (1);
   }
 
  /*

I added a sleep(1) call to prevent this loop from eating up 100% cpu as
it currently does. Do you think you could carry this issue and my
suggested patch upstream?

Thank you very much already!

Cheers,

Fabian

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: