Blocking call to connect()

Daniel.Veillard at imag.fr Daniel.Veillard at imag.fr
Tue Mar 18 09:32:10 PST 1997


  Hi,

--- mode advertising on ---

I now have a version of Amaya embedding Kaffe and using the Jigsaw
Java client classes for the network accesses (in replacement of the
libWWW). The next releases of Amaya will integrate this change, will
be available to W3C members at the end of the month, and the public
source release will occur one month later (end April) :-)
I will present this work at the WWW6 Conf Developer's day (Santa Clara
Friday April 11), I will also be at the Linux Expo on Saturday April 5.

--- switching to tech mode ---

One of the point I was finding annoying in the Java-ized version of
Amaya is the fact that connect() call is blocking. Comparing the strace
obtained by both version of Amaya I noticed that Kaffe was using immediatly
the socket :

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 6
connect(6, {sin_family=AF_INET, sin_port=htons(80), sin_a...

while the libWWW version was fist turning the socket in non-blocking
mode :

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 21
fcntl(21, F_GETFL)                      = 0x2 (flags O_RDWR)
fcntl(21, F_SETFL, O_RDWR|O_NONBLOCK)   = 0
connect(21, {sin_family=AF_INET, sin_port=htons(80), sin_addr

and was using select later on to get the result of the connexion.
Digging in threadCalls.c I found there was code for doing exactly this
controlled by the BLOCKING_CALLS definition set up in the 
kaffe-0.8.2/config/config-hacks.h file:
----------------------------------------------------------------------
/* We force the use of blocking calls for all I/O at the moment.  This
 * means we use select to check read and writes before they're done
 * rather than 'unblocking' the relevant file descriptors which can cause
 * problems where file handles are shared between Kaffe and other programs
 * (typically this is stdio, stdout and stderr).
 */
#define BLOCKING_CALLS
------------------------------------------------------------------------
This is Ok for me, except that connect() is not something we can select()
on ... It seems that the standard way to do non-blocking connect() is to
set up O_NONBLOCK, then the connect call returns EINPROGRESS or EAGAIN ...

I aggree that setting-up non-blocking behaviour may give troubles for
"standard descriptors" but in the case of the connect() call this is 
annoying. BTW once the connection is made the BLOCKING_CALLS + select()
approach is fine for me.

So I ended with the following patch, setting up O_NONBLOCK only during the
connect() call :
----------------------------- patch.connect --------------------------
Index: kaffe-0.8.2/kaffe/kaffevm/threadCalls.c
===================================================================
RCS file: /sources/cvsroot/opera/kaffe-0.8.2/kaffe/kaffevm/threadCalls.c,v
retrieving revision 1.1.1.1
diff -p -r1.1.1.1 threadCalls.c
*** threadCalls.c	1997/03/07 10:52:31	1.1.1.1
--- threadCalls.c	1997/03/18 17:09:10
*************** threadedConnect(int fd, struct sockaddr*
*** 122,127 ****
--- 122,151 ----
  		blockOnFile(fd, TH_CONNECT);
  		r = 0; /* Assume it's okay when we get released */
  	}
+ #elif defined(HAVE_FCNTL) && defined(O_NONBLOCK)
+ 	int s;
+ 	/* Make non-blocking */
+ 	s = fcntl(fd, F_GETFL, 0);
+ 	r = fcntl(fd, F_SETFL, s|O_NONBLOCK);
+ 
+ 	if (r < 0) {
+ 	    /* switching to non-blocking mode failed ... */
+ 	    do {
+ 		    r = connect(fd, addr, len);
+ 	    } while ((r < 0) && (errno == EINTR || errno == EALREADY));
+ 	    if (r < 0 && errno == EISCONN) {
+ 		    r = 0;
+ 	    }
+ 	    /* switch back to blocking mode */
+ 	    fcntl(fd, F_SETFL, s);
+ 	} else {
+ 	    /* use the non-blocking method */
+ 	    r = connect(fd, addr, len);
+ 	    if ((r < 0) && (errno == EINPROGRESS || errno == EALREADY || errno == 
EWOULDBLOCK || errno == EINTR)) {
+ 		    blockOnFile(fd, TH_CONNECT);
+ 		    r = 0; /* Assume it's okay when we get released */
+ 	    }
+ 	}
  #else
  	do {
  		r = connect(fd, addr, len);
-------------------------------- end of patch.connect ------------------

Any opinion on this ? I would also love a patch for non blocking DNS lookup,
alas it seems to be nearly impossible to do in a portable way :-(, UNIX and
POSIX doesn't seem to offer standardized way to get the name resolution server
addresses ...

  Daniel

-- 
Daniel Veillard at w3.org      | W3C / INRIA Rhone-Alpes | Today's Bookmarks :
Daniel.Veillard at inrialpes.fr| 655 av de l'Europe      | Linux, WWW, Java,
Tel : +33 04 76 61 53 85    | 38330 Montbonnot        | badminton, Kaffe,
Fax : +33 04 76 54 76 15    | France                  | Amaya and CSS.
Home: +33 04 76 63 05 86    | http://opera.inrialpes.fr/veillard




More information about the kaffe mailing list