Merge "usblib: fix race & delay waiting for perms on open"
am: 255c43cd05
Change-Id: Idd9ff3980083bb02e8be57d11d2cf5220d613be0
This commit is contained in:
commit
20346c2336
1 changed files with 28 additions and 18 deletions
|
|
@ -324,29 +324,39 @@ void usb_host_run(struct usb_host_context *context,
|
||||||
|
|
||||||
struct usb_device *usb_device_open(const char *dev_name)
|
struct usb_device *usb_device_open(const char *dev_name)
|
||||||
{
|
{
|
||||||
int fd, did_retry = 0, writeable = 1;
|
int fd, attempts, writeable = 1;
|
||||||
|
const int SLEEP_BETWEEN_ATTEMPTS_US = 100000; /* 100 ms */
|
||||||
|
const int64_t MAX_ATTEMPTS = 10; /* 1s */
|
||||||
D("usb_device_open %s\n", dev_name);
|
D("usb_device_open %s\n", dev_name);
|
||||||
|
|
||||||
retry:
|
/* Hack around waiting for permissions to be set on the USB device node.
|
||||||
fd = open(dev_name, O_RDWR);
|
* Should really be a timeout instead of attempt count, and should REALLY
|
||||||
if (fd < 0) {
|
* be triggered by the perm change via inotify rather than polling.
|
||||||
/* if we fail, see if have read-only access */
|
*/
|
||||||
fd = open(dev_name, O_RDONLY);
|
for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) {
|
||||||
D("usb_device_open open returned %d errno %d\n", fd, errno);
|
if (access(dev_name, R_OK | W_OK) == 0) {
|
||||||
if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) {
|
writeable = 1;
|
||||||
/* work around race condition between inotify and permissions management */
|
break;
|
||||||
sleep(1);
|
} else {
|
||||||
did_retry = 1;
|
if (access(dev_name, R_OK) == 0) {
|
||||||
goto retry;
|
/* double check that write permission didn't just come along too! */
|
||||||
|
writeable = (access(dev_name, R_OK | W_OK) == 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* not writeable or readable - sleep and try again. */
|
||||||
if (fd < 0)
|
D("usb_device_open no access sleeping\n");
|
||||||
return NULL;
|
usleep(SLEEP_BETWEEN_ATTEMPTS_US);
|
||||||
writeable = 0;
|
|
||||||
D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (writeable) {
|
||||||
|
fd = open(dev_name, O_RDWR);
|
||||||
|
} else {
|
||||||
|
fd = open(dev_name, O_RDONLY);
|
||||||
|
}
|
||||||
|
D("usb_device_open open returned %d writeable %d errno %d\n", fd, writeable, errno);
|
||||||
|
if (fd < 0) return NULL;
|
||||||
|
|
||||||
struct usb_device* result = usb_device_new(dev_name, fd);
|
struct usb_device* result = usb_device_new(dev_name, fd);
|
||||||
if (result)
|
if (result)
|
||||||
result->writeable = writeable;
|
result->writeable = writeable;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue