Subject: kern/33452: ugen: timeout does not work in function ugen_do_read (interrupt mode)
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <NevilTh@nat.com.au>
List: netbsd-bugs
Date: 05/10/2006 10:19:47
>Number: 33452
>Category: kern
>Synopsis: ugen: timeout does not work in function ugen_do_read (interrupt mode)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed May 10 10:19:47 +0000 2006
>Originator: Nevil Thatcher
>Release: netBSD 3.0 amd64
>Organization:
>Environment:
NetBSD lamborghini.nat.com.au 3.0.0_STABLE NetBSD 3.0.0_STABLE (lamborghini) #9: Sat Mar 11 11:10:07 EST 2006 nevil@lamborghini.nat.com.au:/usr/src/sys/arch/amd64/compile/lamborghini amd64
>Description:
This has come about whilst trying to get nut (ups monitoring) software operational under netBSD. Nut uses libusb as the layer to access usb devices(/dev/ugen), the device I am using being a MGE Nova 1100 UPS.
Software versions are:
netBSD 3.0_STABLE (amd64)
libusb 0.1.12
nut 2.0.3
Libusb offers a function usb_interrupt_read, the function looks like
int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
A call to this should return with *char buffer filled with data from usb device OR timeout after int timeout seconds.
Note: timeout is set within usb_interrup_read with the following call
ret = ioctl(fd, USB_SET_TIMEOUT, &timeout);
The problem seems to be that the dev/ugen code ugen_do_read does not respect this timeout and will not return until such time as data is returned from the usb device.
End result is that when libusb usb_interrupt_read is called it won’t return until data is received from the usb device and the buffer filled, so effectively hangs.
>How-To-Repeat:
Install
libusb 0.1.12
nut 2.0.3 (after installation move to work directory and do
make usb
make installusb
to get usb support)
Remove uhid from kernel config , recompile and install
Connect UPS
Run /usr/local/libexec/nut/newhidups -u root -DDDDD /dev/ugen0 to run in debug mode.
Following output is observed..
--cut
process_status_info: !shutdownimm
entering string_to_path()
Looking up UPS
Looking up PowerSummary
Looking up PresentStatus
Looking up BelowRemainingCapacityLimit
Report : (8 bytes) => 02 23 00 01 00 80 FF FF
hu_find_infoval: searching for value = 0
hu_find_infoval: found !lowbatt (value: 0)
process_status_info: !lowbatt
new connection on fd 7
upsdrv_updateinfo...
Waiting for notifications...
And here it sits indefinitly.
Debugging has identified that at this point it is sitting in ugen_do_read waiting for data from device.
>Fix:
ugen_do_read should respect timeout set by
ioctl(fd, USB_SET_TIMEOUT, &timeout)