unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* [PATCH] nonblocking write/recv/send/connect/accept
@ 2002-03-27 19:03 Christopher Cramer
  2002-05-22 13:20 ` Marius Vollmer
  2002-06-01 15:58 ` Marius Vollmer
  0 siblings, 2 replies; 5+ messages in thread
From: Christopher Cramer @ 2002-03-27 19:03 UTC (permalink / raw)


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 @@
 \f
 
 #include <errno.h>
+#include <fcntl.h>
 
 #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 <crayc@pyro.net> <http://www.pyro.net/~crayc/>
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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] nonblocking write/recv/send/connect/accept
  2002-03-27 19:03 [PATCH] nonblocking write/recv/send/connect/accept Christopher Cramer
@ 2002-05-22 13:20 ` Marius Vollmer
  2002-06-01 15:58 ` Marius Vollmer
  1 sibling, 0 replies; 5+ messages in thread
From: Marius Vollmer @ 2002-05-22 13:20 UTC (permalink / raw)
  Cc: guile-devel

Christopher Cramer <crayc@pyro.net> writes:

> Here it is.

Thanks!  Sorry for the looong delay.  I will get to this 'asap'. :-/

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] nonblocking write/recv/send/connect/accept
  2002-03-27 19:03 [PATCH] nonblocking write/recv/send/connect/accept Christopher Cramer
  2002-05-22 13:20 ` Marius Vollmer
@ 2002-06-01 15:58 ` Marius Vollmer
  2002-06-29  1:07   ` Christopher Cramer
  1 sibling, 1 reply; 5+ messages in thread
From: Marius Vollmer @ 2002-06-01 15:58 UTC (permalink / raw)
  Cc: guile-devel

Christopher Cramer <crayc@pyro.net> writes:

> 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 =^(.

Right, I have to trust you that it works :-)

The patch contains a lot of code of the form

      {
	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");
	  }
      }

Could you try to collect this pattern into its own set of functions
(ala fport_wait_for_input)?  I think this will make the code much
cleaner.

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] nonblocking write/recv/send/connect/accept
  2002-06-01 15:58 ` Marius Vollmer
@ 2002-06-29  1:07   ` Christopher Cramer
  2002-06-29 11:50     ` Marius Vollmer
  0 siblings, 1 reply; 5+ messages in thread
From: Christopher Cramer @ 2002-06-29  1:07 UTC (permalink / raw)
  Cc: Christopher Cramer, guile-devel

On Sat, Jun 01, 2002 at 05:58:29PM +0200, Marius Vollmer wrote:
> Could you try to collect this pattern into its own set of functions
> (ala fport_wait_for_input)?  I think this will make the code much
> cleaner.

One thing is, we need functions in both socket.c and fports.c, and
fport_wait_for_input is static. Should I put the functions in both files,
or make them extern?

-- 
Christopher Cramer <crayc@pyro.net> <http://www.pyro.net/~crayc/>
On résiste à l'invasion des armées; on ne résiste pas à l'invasion
des idées.  -- Victor Hugo

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] nonblocking write/recv/send/connect/accept
  2002-06-29  1:07   ` Christopher Cramer
@ 2002-06-29 11:50     ` Marius Vollmer
  0 siblings, 0 replies; 5+ messages in thread
From: Marius Vollmer @ 2002-06-29 11:50 UTC (permalink / raw)
  Cc: guile-devel

Christopher Cramer <crayc@pyro.net> writes:

> On Sat, Jun 01, 2002 at 05:58:29PM +0200, Marius Vollmer wrote:
> > Could you try to collect this pattern into its own set of functions
> > (ala fport_wait_for_input)?  I think this will make the code much
> > cleaner.
> 
> One thing is, we need functions in both socket.c and fports.c, and
> fport_wait_for_input is static. Should I put the functions in both files,
> or make them extern?

The point is to collect similar code, so I'd say we should have only
one copy of a function.  Also, there might be more opportunities to
use it in the future.  A good place to put it would be iselect.c, I
think.

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-06-29 11:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-03-27 19:03 [PATCH] nonblocking write/recv/send/connect/accept Christopher Cramer
2002-05-22 13:20 ` Marius Vollmer
2002-06-01 15:58 ` Marius Vollmer
2002-06-29  1:07   ` Christopher Cramer
2002-06-29 11:50     ` Marius Vollmer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).