From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: rixed@happyleptic.org Newsgroups: gmane.lisp.guile.user Subject: Re: Guile hangs for minutes when many files are opened (1.8.7) Date: Mon, 4 Jul 2011 11:33:06 +0200 Message-ID: <20110704093306.GA27433@ccellier.rd.happyleptic.org> References: <20110614072126.GA15414@ccellier.rd.happyleptic.org> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="jRHKVT23PllUwdXP" X-Trace: dough.gmane.org 1309772030 1231 80.91.229.12 (4 Jul 2011 09:33:50 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 4 Jul 2011 09:33:50 +0000 (UTC) To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Mon Jul 04 11:33:42 2011 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1QdfXB-0003Yz-Jd for guile-user@m.gmane.org; Mon, 04 Jul 2011 11:33:41 +0200 Original-Received: from localhost ([::1]:60311 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QdfXA-0003dG-6p for guile-user@m.gmane.org; Mon, 04 Jul 2011 05:33:40 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:49908) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QdfWs-0003cP-Do for guile-user@gnu.org; Mon, 04 Jul 2011 05:33:23 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QdfWq-0001w8-3B for guile-user@gnu.org; Mon, 04 Jul 2011 05:33:21 -0400 Original-Received: from dangi.happyleptic.org ([92.243.13.193]:57768) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QdfWp-0001uW-Ev for guile-user@gnu.org; Mon, 04 Jul 2011 05:33:19 -0400 Original-Received: from extranet.securactive.org ([82.234.213.170] helo=ccellier.rd.securactive.lan) by dangi.happyleptic.org with esmtp (Exim 4.72) (envelope-from ) id 1QdfZb-0005Tq-I9 for guile-user@gnu.org; Mon, 04 Jul 2011 11:36:11 +0200 Original-Received: from rixed by ccellier.rd.securactive.lan with local (Exim 4.72) (envelope-from ) id 1QdfWc-0007AV-Hw for guile-user@gnu.org; Mon, 04 Jul 2011 11:33:06 +0200 Mail-Followup-To: rixed@happyleptic.org, guile-user@gnu.org Content-Disposition: inline In-Reply-To: <20110614072126.GA15414@ccellier.rd.happyleptic.org> User-Agent: Mutt/1.5.20 (2009-06-14) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 92.243.13.193 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:8676 Archived-At: --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Well, the bug is more annoying than previously though since guile use select on various ports internally. The attached patch fixes all occurrences of such uses. The scm_std_poll function API is ugly, though. I'd really like this issue being addressed in current guile branch either with this patch or a better one. --jRHKVT23PllUwdXP Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="select.patch" 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, --jRHKVT23PllUwdXP--