From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Christopher Cramer Newsgroups: gmane.lisp.guile.devel Subject: [PATCH] nonblocking write/recv/send/connect/accept Date: Wed, 27 Mar 2002 13:03:51 -0600 Sender: guile-devel-admin@gnu.org Message-ID: <20020327130351.B27416@kiwi.pyrotechnics.com> NNTP-Posting-Host: localhost.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Trace: main.gmane.org 1017255820 5083 127.0.0.1 (27 Mar 2002 19:03:40 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Wed, 27 Mar 2002 19:03:40 +0000 (UTC) Original-Received: from fencepost.gnu.org ([199.232.76.164]) by main.gmane.org with esmtp (Exim 3.33 #1 (Debian)) id 16qIhv-0001Js-00 for ; Wed, 27 Mar 2002 20:03:39 +0100 Original-Received: from localhost ([127.0.0.1] helo=fencepost.gnu.org) by fencepost.gnu.org with esmtp (Exim 3.34 #1 (Debian)) id 16qIhb-0006rh-00; Wed, 27 Mar 2002 14:03:19 -0500 Original-Received: from pyro.net ([207.7.10.2] helo=kiwi.pyro.net) by fencepost.gnu.org with smtp (Exim 3.34 #1 (Debian)) id 16qIfD-0006kA-00 for ; Wed, 27 Mar 2002 14:00:51 -0500 Original-Received: (qmail 28871 invoked by uid 8610); 27 Mar 2002 19:03:51 -0000 Original-To: guile-devel@gnu.org Mail-Followup-To: guile-devel@gnu.org Content-Disposition: inline User-Agent: Mutt/1.2.5i Errors-To: guile-devel-admin@gnu.org X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.0.5 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Developers list for Guile, the GNU extensibility library List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.lisp.guile.devel:213 X-Report-Spam: http://spam.gmane.org/gmane.lisp.guile.devel:213 Here it is. scm_connect was a little tricky and it actually looks very ugly to me, but the connect system call was really not designed for this sort of thing =^(. It's a patch for stable, but I suspect it changes too much to actually make it into stable. It applies to unstable without any problems though. * fports.c (scm_fdes_wait_for_input): raise exception if scm_internal_select fails. * fports.c (write_all, fport_flush), socket.c (scm_connect, scm_accept, scm_recv, scm_send): call scm_internal_select, to keep from from blocking other cooperative threads. Index: libguile/fports.c =================================================================== RCS file: /cvsroot/guile/guile/guile-core/libguile/fports.c,v retrieving revision 1.100.2.4 diff -u -r1.100.2.4 fports.c --- libguile/fports.c 14 Mar 2002 05:26:15 -0000 1.100.2.4 +++ libguile/fports.c 27 Mar 2002 18:38:00 -0000 @@ -537,13 +537,16 @@ if (flags == -1) scm_syserror ("scm_fdes_wait_for_input"); if (!(flags & O_NONBLOCK)) - do - { - FD_ZERO (&readfds); - FD_SET (fdes, &readfds); - n = scm_internal_select (fdes + 1, &readfds, NULL, NULL, NULL); - } - while (n == -1 && errno == EINTR); + { + do + { + FD_ZERO (&readfds); + FD_SET (fdes, &readfds); + n = scm_internal_select (fdes + 1, &readfds, NULL, NULL, NULL); + } + while (n == -1 && errno == EINTR); + if (n == -1) scm_syserror ("scm_fdes_wait_for_input"); + } } } #endif @@ -647,6 +650,28 @@ { size_t done; +#ifdef GUILE_ISELECT + { + int n; + SELECT_TYPE writefds; + int flags = fcntl (fdes, F_GETFL); + + if (flags == -1) + scm_syserror ("write_all"); + if (!(flags & O_NONBLOCK)) + { + do + { + FD_ZERO (&writefds); + FD_SET (fdes, &writefds); + n = scm_internal_select (fdes + 1, NULL, &writefds, NULL, NULL); + } + while (n == -1 && errno == EINTR); + if (n == -1) scm_syserror ("write_all"); + } + } +#endif /* GUILE_ISELECT */ + SCM_SYSCALL (done = write (fdes, data, remaining)); if (done == -1) @@ -727,12 +752,35 @@ unsigned char *ptr = pt->write_buf; long init_size = pt->write_pos - pt->write_buf; long remaining = init_size; + int fd = fp->fdes; while (remaining > 0) { long count; - SCM_SYSCALL (count = write (fp->fdes, ptr, remaining)); +#ifdef GUILE_ISELECT + { + int n; + SELECT_TYPE writefds; + int flags = fcntl (fd, F_GETFL); + + if (flags == -1) + scm_syserror ("fport_flush"); + if (!(flags & O_NONBLOCK)) + { + do + { + FD_ZERO (&writefds); + FD_SET (fd, &writefds); + n = scm_internal_select (fd + 1, NULL, &writefds, NULL, NULL); + } + while (n == -1 && errno == EINTR); + if (n == -1) scm_syserror ("fport_flush"); + } + } +#endif /* GUILE_ISELECT */ + + SCM_SYSCALL (count = write (fd, ptr, remaining)); if (count < 0) { /* error. assume nothing was written this call, but @@ -755,7 +803,7 @@ char buf[11]; write (2, msg, strlen (msg)); - sprintf (buf, "%d\n", fp->fdes); + sprintf (buf, "%d\n", fd); write (2, buf, strlen (buf)); count = remaining; Index: libguile/socket.c =================================================================== RCS file: /cvsroot/guile/guile/guile-core/libguile/socket.c,v retrieving revision 1.80.2.3 diff -u -r1.80.2.3 socket.c --- libguile/socket.c 15 Mar 2002 09:23:19 -0000 1.80.2.3 +++ libguile/socket.c 27 Mar 2002 18:38:03 -0000 @@ -43,11 +43,13 @@ #include +#include #include "libguile/_scm.h" #include "libguile/unif.h" #include "libguile/feature.h" #include "libguile/fports.h" +#include "libguile/iselect.h" #include "libguile/strings.h" #include "libguile/vectors.h" @@ -809,6 +811,83 @@ "The return value is unspecified.") #define FUNC_NAME s_scm_connect { +#ifdef GUILE_ISELECT + int fd; + struct sockaddr *soka; + int size; + long flags; + int saved_errno; + + sock = SCM_COERCE_OUTPORT (sock); + SCM_VALIDATE_OPFPORT (1,sock); + SCM_VALIDATE_INUM (2,fam); + fd = SCM_FPORT_FDES (sock); + soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME, + &size); + if (-1 == (flags = fcntl(fd, F_GETFL))) SCM_SYSERROR; + if (!(flags & O_NONBLOCK)) + { + int rc; + + if (fcntl (fd, F_SETFL, flags | O_NONBLOCK)) SCM_SYSERROR; + rc = connect (fd, soka, size); + + if (rc && errno == EINPROGRESS) + { + SELECT_TYPE writefds; + socklen_t len; + + free (soka); + do + { + FD_ZERO (&writefds); + FD_SET (fd, &writefds); + rc = scm_internal_select(fd + 1, NULL, &writefds, + NULL, NULL); + } + while (rc == -1 && errno == EINTR); + saved_errno = errno; + if (fcntl (fd, F_SETFL, flags)) SCM_SYSERROR; + if (rc == -1) + { + errno = saved_errno; + SCM_SYSERROR; + } + + len = sizeof (rc); + if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &rc, &len)) SCM_SYSERROR; + if (rc) + { + errno = rc; + SCM_SYSERROR; + } + } + else if (rc) + { + saved_errno = errno; + free (soka); + if (fcntl (fd, F_SETFL, flags)) SCM_SYSERROR; + errno = saved_errno; + SCM_SYSERROR; + } + else + { + free (soka); + if (fcntl (fd, F_SETFL, flags)) SCM_SYSERROR; + } + } + else + { + if (connect (fd, soka, size)) + { + saved_errno = errno; + free (soka); + errno = saved_errno; + SCM_SYSERROR; + } + } + return SCM_UNSPECIFIED; +#else /* GUILE_ISELECT */ int fd; struct sockaddr *soka; int size; @@ -822,13 +901,15 @@ if (connect (fd, soka, size) == -1) { int save_errno = errno; - + free (soka); errno = save_errno; SCM_SYSERROR; } + free (soka); return SCM_UNSPECIFIED; +#endif /* GUILE_ISELECT */ } #undef FUNC_NAME @@ -1019,6 +1100,29 @@ sock = SCM_COERCE_OUTPORT (sock); SCM_VALIDATE_OPFPORT (1, sock); fd = SCM_FPORT_FDES (sock); + +#ifdef GUILE_ISELECT + { + int n; + SELECT_TYPE readfds; + int flags = fcntl (fd, F_GETFL); + + if (flags == -1) + scm_syserror ("scm_accept"); + if (!(flags & O_NONBLOCK)) + { + do + { + FD_ZERO (&readfds); + FD_SET (fd, &readfds); + n = scm_internal_select (fd + 1, &readfds, NULL, NULL, NULL); + } + while (n == -1 && errno == EINTR); + if (n == -1) scm_syserror ("scm_accept"); + } + } +#endif /* GUILE_ISELECT */ + newfd = accept (fd, addr, &addr_size); if (newfd == -1) SCM_SYSERROR; @@ -1101,6 +1205,28 @@ SCM_VALIDATE_INUM_DEF_COPY (3,flags,0,flg); fd = SCM_FPORT_FDES (sock); +#ifdef GUILE_ISELECT + { + int n; + SELECT_TYPE readfds; + int flags = fcntl (fd, F_GETFL); + + if (flags == -1) + scm_syserror ("scm_recv"); + if (!(flags & O_NONBLOCK)) + { + do + { + FD_ZERO (&readfds); + FD_SET (fd, &readfds); + n = scm_internal_select (fd + 1, &readfds, NULL, NULL, NULL); + } + while (n == -1 && errno == EINTR); + if (n == -1) scm_syserror ("scm_recv"); + } + } +#endif /* GUILE_ISELECT */ + SCM_SYSCALL (rv = recv (fd, SCM_STRING_CHARS (buf), SCM_STRING_LENGTH (buf), flg)); if (rv == -1) SCM_SYSERROR; @@ -1134,6 +1260,28 @@ SCM_VALIDATE_STRING (2, message); SCM_VALIDATE_INUM_DEF_COPY (3,flags,0,flg); fd = SCM_FPORT_FDES (sock); + +#ifdef GUILE_ISELECT + { + int n; + SELECT_TYPE writefds; + int flags = fcntl (fd, F_GETFL); + + if (flags == -1) + scm_syserror ("scm_send"); + if (!(flags & O_NONBLOCK)) + { + do + { + FD_ZERO (&writefds); + FD_SET (fd, &writefds); + n = scm_internal_select (fd + 1, NULL, &writefds, NULL, NULL); + } + while (n == -1 && errno == EINTR); + if (n == -1) scm_syserror ("scm_send"); + } + } +#endif /* GUILE_ISELECT */ SCM_SYSCALL (rv = send (fd, SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message), flg)); if (rv == -1) -- Christopher Cramer Quoi que vous fassiez, écrasez l'infâme, et aimez qui vous aime. -- Voltaire _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://mail.gnu.org/mailman/listinfo/guile-devel