diff --git a/configure.in b/configure.in index 217ac83..ea26b5c 100644 --- a/configure.in +++ b/configure.in @@ -661,7 +661,7 @@ AC_CHECK_HEADERS([complex.h fenv.h io.h libc.h limits.h malloc.h memory.h proces regex.h rxposix.h rx/rxposix.h sys/dir.h sys/ioctl.h sys/select.h \ sys/time.h sys/timeb.h sys/times.h sys/stdtypes.h sys/types.h \ sys/utime.h time.h unistd.h utime.h pwd.h grp.h sys/utsname.h \ -direct.h strings.h machine/fpu.h]) +poll.h direct.h strings.h machine/fpu.h]) # "complex double" is new in C99, and "complex" is only a keyword if # is included @@ -755,7 +755,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h]) # isblank - available as a GNU extension or in C99 # _NSGetEnviron - Darwin specific # -AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid fesetround ftime ftruncate fchown getcwd geteuid gettimeofday gmtime_r ioctl lstat mkdir mknod nice pipe _pipe readdir_r readdir64_r readlink rename rmdir select setegid seteuid setlocale setpgid setsid sigaction siginterrupt stat64 strftime strptime symlink sync sysconf tcgetpgrp tcsetpgrp times uname waitpid strdup system usleep atexit on_exit chown link fcntl ttyname getpwent getgrent kill getppid getpgrp fork setitimer getitimer strchr strcmp index bcopy memcpy rindex truncate unsetenv isblank _NSGetEnviron strncasecmp]) +AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid fesetround ftime ftruncate fchown getcwd geteuid gettimeofday gmtime_r ioctl lstat mkdir mknod nice pipe _pipe readdir_r readdir64_r readlink rename rmdir poll select setegid seteuid setlocale setpgid setsid sigaction siginterrupt stat64 strftime strptime symlink sync sysconf tcgetpgrp tcsetpgrp times uname waitpid strdup system usleep atexit on_exit chown link fcntl ttyname getpwent getgrent kill getppid getpgrp fork setitimer getitimer strchr strcmp index bcopy memcpy rindex truncate unsetenv isblank _NSGetEnviron strncasecmp]) # Reasons for testing: # netdb.h - not in mingw diff --git a/libguile/fports.c b/libguile/fports.c index 007ee3f..8e16a55 100644 --- a/libguile/fports.c +++ b/libguile/fports.c @@ -46,7 +46,9 @@ #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE #include #endif - +#ifdef HAVE_POLL_H +#include +#endif #include #include @@ -485,7 +487,14 @@ scm_fdes_to_port (int fdes, char *mode, SCM name) static int fport_input_waiting (SCM port) { -#ifdef HAVE_SELECT +#ifdef HAVE_POLL + int fdes = SCM_FSTREAM (port)->fdes; + struct pollfd pollfd = { fdes, POLLIN, 0 }; + if (poll(&pollfd, 1, 0) < 0) + scm_syserror ("fport_input_waiting"); + return pollfd.revents & POLLIN ? 1 : 0; + +#elif defined(HAVE_SELECT) int fdes = SCM_FSTREAM (port)->fdes; struct timeval timeout; SELECT_TYPE read_set; @@ -566,7 +575,6 @@ fport_wait_for_input (SCM port) if (!fport_input_waiting (port)) { int n; - SELECT_TYPE readfds; int flags = fcntl (fdes, F_GETFL); if (flags == -1) @@ -574,9 +582,17 @@ fport_wait_for_input (SCM port) if (!(flags & O_NONBLOCK)) do { +#if HAVE_POLL + struct pollfd pollfds[2]; + pollfds[1].fd = fdes; + pollfds[1].events = POLLIN; + n = scm_std_poll (2, pollfds, -1); +#else + SELECT_TYPE readfds; FD_ZERO (&readfds); FD_SET (fdes, &readfds); n = scm_std_select (fdes + 1, &readfds, NULL, NULL, NULL); +#endif } while (n == -1 && errno == EINTR); } diff --git a/libguile/iselect.h b/libguile/iselect.h index b23a641..459e690 100644 --- a/libguile/iselect.h +++ b/libguile/iselect.h @@ -57,6 +57,15 @@ #endif /* no FD_SET */ +#if HAVE_POLL + +#include + +SCM_API int scm_std_poll (int fds, + struct pollfd *pollfds, + int timeout_ms); +#endif + SCM_API int scm_std_select (int fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, diff --git a/libguile/socket.c b/libguile/socket.c index cb954f4..9d9efb6 100644 --- a/libguile/socket.c +++ b/libguile/socket.c @@ -1328,7 +1328,6 @@ SCM_DEFINE (scm_accept, "accept", 1, 0, 0, int newfd; SCM address; SCM newsock; - SELECT_TYPE readfds, exceptfds; socklen_t addr_size = MAX_ADDR_SIZE; scm_t_max_sockaddr addr; @@ -1336,6 +1335,16 @@ SCM_DEFINE (scm_accept, "accept", 1, 0, 0, SCM_VALIDATE_OPFPORT (1, sock); fd = SCM_FPORT_FDES (sock); +#if HAVE_POLL + struct pollfd pollfds[2]; + pollfds[1].fd = fd; + pollfds[1].events = POLLIN | POLLHUP; + + /* Block until something happens on FD, leaving guile mode while + waiting. */ + selected = scm_std_poll (2, pollfds, -1); +#else + SELECT_TYPE readfds, exceptfds; FD_ZERO (&readfds); FD_ZERO (&exceptfds); FD_SET (fd, &readfds); @@ -1345,6 +1354,7 @@ SCM_DEFINE (scm_accept, "accept", 1, 0, 0, waiting. */ selected = scm_std_select (fd + 1, &readfds, NULL, &exceptfds, NULL); +#endif if (selected < 0) SCM_SYSERROR; diff --git a/libguile/threads.c b/libguile/threads.c index f2bb556..16e17e5 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -37,6 +37,10 @@ #include #endif +#ifdef HAVE_POLL_H +#include +#endif + #include "libguile/validate.h" #include "libguile/root.h" #include "libguile/eval.h" @@ -1419,6 +1423,52 @@ scm_threads_mark_stacks (void) /*** Select */ +#if HAVE_POLL +int +scm_std_poll (int nfds, + struct pollfd *pollfds, // first entry is unset, reserved for us + int timeout_ms) +{ + int res, eno, wakeup_fd; + scm_i_thread *t = SCM_I_CURRENT_THREAD; + scm_t_guile_ticket ticket; + + while (scm_i_setup_sleep (t, SCM_BOOL_F, NULL, t->sleep_pipe[1])) + SCM_TICK; + + wakeup_fd = t->sleep_pipe[0]; + ticket = scm_leave_guile (); + + pollfds[0].fd = wakeup_fd; + pollfds[0].events = POLLIN; + + res = poll (pollfds, nfds, timeout_ms); + t->sleep_fd = -1; + eno = errno; + scm_enter_guile (ticket); + + scm_i_reset_sleep (t); + + if (res > 0 && (pollfds[0].revents & POLLIN)) + { + char dummy; + size_t count; + + count = read (wakeup_fd, &dummy, 1); + + pollfds[0].revents = 0; + res -= 1; + if (res == 0) + { + eno = EINTR; + res = -1; + } + } + errno = eno; + return res; +} +#endif + int scm_std_select (int nfds, SELECT_TYPE *readfds,