On Friday 06 January 2012 14:52, Natanael Copa wrote:
> Looking a bit at the code, it appears that it never checks for POLLERR
> or POLLHUP and thus enters an endless loop.
> 
> Doh... it just hit me.
> 
> What happens is, I have an USB keyboard and USB mouse attached to the
> screen. When I power off the screen the keyboard and mouse input
> devices disappear and the file handle in acpid becomes invalid. Since
> nothing checks for POLLERR|POLLHUP it ends up in an endless loop since
> POLLIN was not set.

This is weird, because usually POLLIN would be set too in such a case -
since read() would usually be possible (in a sense that it would not block,
but return EOF or error _immediately_), and therefore poll must indicate that.

Oh well...
 
> I wonder what the proper way to handle this is. Probably do some
> netlink stuff to detect new devices for acpid?

Another solution is just to restart acpid.
Best to do it automatically from hotplug helper...

> Quick workaround would be to just close fd on POLLHUP or POLLERR:

> diff --git a/util-linux/acpid.c b/util-linux/acpid.c
> index 6e7321b..3d723c0 100644
> --- a/util-linux/acpid.c
> +++ b/util-linux/acpid.c
> @@ -292,6 +292,11 @@ int acpid_main(int argc UNUSED_PARAM, char **argv)
>                 for (i = 0; i < nfd; i++) {
>                         const char *event = NULL;
> 
> +                       if (pfd[i].revents & (POLLERR | POLLHUP)) {
> +                               close(pfd[i].fd);
> +                               pfd[i].fd = -1;
> +                       }
> +

I'm a bit surprised this would work: I don't remember any special case
in poll() to ignore fds < 0, so it _might_ start returning POLLNVAL
on this pfd[i] from now on.

Does it work if instead of closing pfd[i].fd, you set pfd[i].events = 0?

A cleaner solution is to shift all pfd[] elements one element down
starting from [i], and do nfd--. Something like this:

                        if (!(pfd[i].revents & POLLIN)) {
                                if (pfd[i].revents == 0)
                                        continue; /* this fd has nothing */

                                /* Likely POLLERR, POLLHUP, POLLNVAL.
                                 * Do not listen on this fd anymore.
                                 */
                                close(pfd[i].fd);
                                nfd--;
                                for (; i < nfd; i++)
                                        pfd[i].fd = pfd[i + 1].fd;
                                break; /* do poll() again */
                        }



With your fix, what happens when you power your screen back on?
I guess the keyboard and mouse ACPI events are no longer detected by acpid,
right?

-- 
vda
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to