From: Christopher Cramer <crayc@pyro.net>
Subject: [PATCH] nonblocking write/recv/send/connect/accept
Date: Wed, 27 Mar 2002 13:03:51 -0600 [thread overview]
Message-ID: <20020327130351.B27416@kiwi.pyrotechnics.com> (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
next reply other threads:[~2002-03-27 19:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-03-27 19:03 Christopher Cramer [this message]
2002-05-22 13:20 ` [PATCH] nonblocking write/recv/send/connect/accept Marius Vollmer
2002-06-01 15:58 ` Marius Vollmer
2002-06-29 1:07 ` Christopher Cramer
2002-06-29 11:50 ` Marius Vollmer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20020327130351.B27416@kiwi.pyrotechnics.com \
--to=crayc@pyro.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).