* [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).