-
-
Notifications
You must be signed in to change notification settings - Fork 399
Description
As discussed in #2742 (comment) a NUT driver (any one of them) does some work in upsdrv_updateinfo(), effectively sleeps for the remainder of timeout in dstate_poll_fds() (if no extrafd like those for a serial port or a raw network socket gets bytes incoming, or a sockfd internal to dstate.c), and only then gets to run upsdrv_updateinfo() again and perhaps notice the absence of the device as reported by libusb.
NOTE: Currently extrafd is ignored in WIN32 builds, but we do handle sockfd so this might be extensible eventually. See also https://learn.microsoft.com/en-us/windows/win32/winsock/select-and-fd---2
Currently this shortcut is not really used by the majority of drivers, so they normally all "suffer" a standard delay between loop cycles, with the few hits being:
:; git grep extrafd
drivers/apcsmart-old.c: extrafd = upsfd;
drivers/apcsmart.c: upsfd = extrafd = ser_open(device_path);
drivers/clone-outlet.c: extrafd = upsfd = sstate_connect();
drivers/clone-outlet.c: extrafd = upsfd = sstate_connect();
drivers/clone.c: extrafd = upsfd = sstate_connect();
drivers/clone.c: extrafd = upsfd = sstate_connect();
drivers/dstate.c:int dstate_poll_fds(struct timeval timeout, TYPE_FD arg_extrafd)
drivers/dstate.c: if (VALID_FD(arg_extrafd)) {
drivers/dstate.c: FD_SET(arg_extrafd, &rfds);
drivers/dstate.c: if (arg_extrafd > maxfd) {
drivers/dstate.c: maxfd = arg_extrafd;
drivers/dstate.c: if (VALID_FD(arg_extrafd) && (FD_ISSET(arg_extrafd, &rfds))) {
drivers/dstate.c: NUT_UNUSED_VARIABLE(arg_extrafd);
drivers/dstate.c: if (VALID_FD(arg_extrafd)) {
drivers/dstate.c: rfds[maxfd] = arg_extrafd;
drivers/dstate.c: if (VALID_FD(arg_extrafd) && (ret == arg_extrafd)) {
drivers/dstate.h:int dstate_poll_fds(struct timeval timeout, TYPE_FD extrafd);
drivers/main.c:TYPE_FD extrafd = ERROR_FD;
drivers/main.c: while (!dstate_poll_fds(timeout, extrafd) && !exit_flag) {
drivers/main.c: /* repeat until time is up or extrafd has data */
drivers/main.h:extern TYPE_FD upsfd, extrafd;
drivers/netxml-ups.c:/* TODO: port extrafd to Windows */
drivers/netxml-ups.c: extrafd = ne_sock_fd(sock);
drivers/netxml-ups.c:/* TODO: port extrafd to Windows */
drivers/netxml-ups.c: extrafd = ne_sock_fd(sock);
drivers/apcsmart-old.c: extrafd = upsfd;
drivers/apcsmart.c: upsfd = extrafd = ser_open(device_path);
drivers/clone-outlet.c: extrafd = upsfd = sstate_connect();
drivers/clone-outlet.c: extrafd = upsfd = sstate_connect();
drivers/clone.c: extrafd = upsfd = sstate_connect();
drivers/clone.c: extrafd = upsfd = sstate_connect();
drivers/dstate.c:int dstate_poll_fds(struct timeval timeout, TYPE_FD arg_extrafd)
drivers/dstate.c: if (VALID_FD(arg_extrafd)) {
drivers/dstate.c: FD_SET(arg_extrafd, &rfds);
drivers/dstate.c: if (arg_extrafd > maxfd) {
drivers/dstate.c: maxfd = arg_extrafd;
drivers/dstate.c: if (VALID_FD(arg_extrafd) && (FD_ISSET(arg_extrafd, &rfds))) {
drivers/dstate.c: NUT_UNUSED_VARIABLE(arg_extrafd);
drivers/dstate.c: if (VALID_FD(arg_extrafd)) {
drivers/dstate.c: rfds[maxfd] = arg_extrafd;
drivers/dstate.c: if (VALID_FD(arg_extrafd) && (ret == arg_extrafd)) {
drivers/dstate.h:int dstate_poll_fds(struct timeval timeout, TYPE_FD extrafd);
drivers/main.c:TYPE_FD extrafd = ERROR_FD;
drivers/main.c: while (!dstate_poll_fds(timeout, extrafd) && !exit_flag) {
drivers/main.c: /* repeat until time is up or extrafd has data */
drivers/main.h:extern TYPE_FD upsfd, extrafd;
drivers/netxml-ups.c:/* TODO: port extrafd to Windows */
drivers/netxml-ups.c: extrafd = ne_sock_fd(sock);
drivers/netxml-ups.c:/* TODO: port extrafd to Windows */
drivers/netxml-ups.c: extrafd = ne_sock_fd(sock);
As documented in https://libusb.sourceforge.io/api-1.0/group__libusb__poll.html#ga54c27dcf8a95d2a3a03cfb7dd37eae63 and https://libusb.sourceforge.io/api-1.0/structlibusb__pollfd.html the LibUSB-1.0 API actually allows programs to see the collection of file descriptors (and their event flags from poll.h) associated with a context, so we have a chance to redesign driver loops (not sure OTOH there's one or more extrafd equivalents in our case) in such a way that we can react more quickly to USB device events. Note there does not seem to be any similar facility in older LibUSB-0.1 headers.
This idea may also help with #2609 as well.