/src/common/xpoll.c

https://code.google.com/ · C · 207 lines · 148 code · 27 blank · 32 comment · 44 complexity · d0a03a4427b3a9c7620e586fc9a6850e MD5 · raw file

  1. /*****************************************************************************\
  2. * $Id$
  3. *****************************************************************************
  4. * Copyright (C) 2001-2006 The Regents of the University of California.
  5. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  6. * Written by Jim Garlick <garlick@llnl.gov>.
  7. * UCRL-CODE-2003-005.
  8. *
  9. * This file is part of Pdsh, a parallel remote shell program.
  10. * For details, see <http://www.llnl.gov/linux/pdsh/>.
  11. *
  12. * Pdsh is free software; you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free
  14. * Software Foundation; either version 2 of the License, or (at your option)
  15. * any later version.
  16. *
  17. * Pdsh is distributed in the hope that it will be useful, but WITHOUT ANY
  18. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  20. * details.
  21. *
  22. * You should have received a copy of the GNU General Public License along
  23. * with Pdsh; if not, write to the Free Software Foundation, Inc.,
  24. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  25. \*****************************************************************************/
  26. #if HAVE_CONFIG_H
  27. # include <config.h>
  28. #endif
  29. #if HAVE_POLL_H
  30. #include <poll.h>
  31. #else
  32. #if HAVE_SYS_POLL_H
  33. #include <sys/poll.h>
  34. #endif /* HAVE_SYS_POLL_H */
  35. #endif /* HAVE_POLL_H */
  36. #include <sys/types.h>
  37. #include <sys/select.h>
  38. #include <sys/time.h>
  39. #if HAVE_UNISTD_H
  40. #include <unistd.h>
  41. #endif
  42. #include <errno.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include "xpoll.h"
  46. #include "xmalloc.h"
  47. #if HAVE_POLL
  48. static int
  49. _poll(struct xpollfd *xfds, unsigned int nfds, int timeout) {
  50. int i, rv;
  51. struct pollfd *pfds = Malloc(nfds * sizeof(struct pollfd));
  52. for (i = 0; i < nfds; i++) {
  53. pfds[i].fd = xfds[i].fd;
  54. pfds[i].events = 0;
  55. pfds[i].revents = 0;
  56. if (xfds[i].events & XPOLLREAD)
  57. pfds[i].events |= POLLIN;
  58. if (xfds[i].events & XPOLLWRITE)
  59. pfds[i].events |= POLLOUT;
  60. }
  61. if ((rv = poll(pfds, nfds, timeout)) < 0) {
  62. Free((void **)&pfds);
  63. return -1;
  64. }
  65. for (i = 0; i < nfds; i++) {
  66. if (pfds[i].revents & POLLIN)
  67. xfds[i].revents |= XPOLLREAD;
  68. if (pfds[i].revents & POLLOUT)
  69. xfds[i].revents |= XPOLLWRITE;
  70. if (pfds[i].revents & POLLERR || pfds[i].revents & POLLHUP)
  71. xfds[i].revents |= XPOLLERR;
  72. if (pfds[i].revents & POLLNVAL)
  73. xfds[i].revents |= XPOLLINVAL;
  74. }
  75. Free((void **)&pfds);
  76. errno = 0;
  77. return rv;
  78. }
  79. #else /* !HAVE_POLL */
  80. static int
  81. _select(struct xpollfd *xfds, unsigned int nfds, int timeout) {
  82. int i, maxfd = -1, inval = 0, rv = -1;
  83. struct timeval tv;
  84. struct timeval *tptr = &tv;
  85. fd_set reads, writes;
  86. if (timeout < 0)
  87. tptr = NULL;
  88. else {
  89. tv.tv_sec = timeout;
  90. tv.tv_usec = 0;
  91. }
  92. /* setup for select() */
  93. FD_ZERO(&reads);
  94. FD_ZERO(&writes);
  95. for (i = 0; i < nfds; i++) {
  96. if (xfds[i].fd >= FD_SETSIZE || xfds[i].fd < 0) {
  97. xfds[i].revents |= XPOLLINVAL;
  98. inval++;
  99. continue;
  100. }
  101. if (xfds[i].events & XPOLLREAD)
  102. FD_SET(xfds[i].fd, &reads);
  103. if (xfds[i].events & XPOLLWRITE)
  104. FD_SET(xfds[i].fd, &writes);
  105. if (xfds[i].fd > maxfd)
  106. maxfd = xfds[i].fd;
  107. }
  108. while (rv == -1) {
  109. if ((rv = select(maxfd + 1, &reads, &writes, NULL, tptr)) < 0) {
  110. if (errno != EBADF)
  111. return -1;
  112. else {
  113. /* check for and remove bad fds */
  114. struct timeval ttv = {0, 1}; /* very very short timeout */
  115. fd_set rds, wrs;
  116. maxfd = -1;
  117. FD_ZERO(&reads);
  118. FD_ZERO(&writes);
  119. for (i = 0; i < nfds; i++) {
  120. if (xfds[i].revents & XPOLLINVAL)
  121. continue;
  122. FD_ZERO(&rds);
  123. FD_ZERO(&wrs);
  124. if (xfds[i].events & XPOLLREAD)
  125. FD_SET(xfds[i].fd, &rds);
  126. if (xfds[i].events & XPOLLWRITE)
  127. FD_SET(xfds[i].fd, &wrs);
  128. if (select(xfds[i].fd + 1, &rds, &wrs, NULL, &ttv) < 0) {
  129. if (errno != EBADF)
  130. return -1;
  131. else {
  132. xfds[i].revents |= XPOLLINVAL;
  133. inval++;
  134. }
  135. }
  136. else {
  137. /* prepare for next select */
  138. if (xfds[i].events & XPOLLREAD)
  139. FD_SET(xfds[i].fd, &reads);
  140. if (xfds[i].events & XPOLLWRITE)
  141. FD_SET(xfds[i].fd, &writes);
  142. if (xfds[i].fd > maxfd)
  143. maxfd = xfds[i].fd;
  144. }
  145. }
  146. }
  147. }
  148. }
  149. for (i = 0; i < nfds; i++) {
  150. /* protect segfault prone FD_ISSET */
  151. if (xfds[i].revents & XPOLLINVAL)
  152. continue;
  153. if (FD_ISSET(xfds[i].fd, &reads))
  154. xfds[i].revents |= XPOLLREAD;
  155. if (FD_ISSET(xfds[i].fd, &writes))
  156. xfds[i].revents |= XPOLLWRITE;
  157. }
  158. errno = 0;
  159. return (rv + inval);
  160. }
  161. #endif /* HAVE_POLL */
  162. int xpoll(struct xpollfd *xfds, int nfds, int timeout) {
  163. int i;
  164. errno = 0;
  165. if (xfds == NULL || nfds <= 0) {
  166. errno = EINVAL;
  167. return -1;
  168. }
  169. for (i = 0; i < nfds; i++) {
  170. xfds[i].revents = 0;
  171. }
  172. #if HAVE_POLL
  173. return _poll(xfds, nfds, timeout);
  174. #else
  175. return _select(xfds, nfds, timeout);
  176. #endif
  177. }
  178. /*
  179. * vi: tabstop=4 shiftwidth=4 expandtab
  180. */