Oz and Mozart Hackers Mailing List

Please help: Trying to implement non-blocking connect in OS module


From: Harmon S. Nine (hnine@netarx.com)
Date: Thu Dec 11 2003 - 22:41:30 CET


Hello all. I'm using OZ in a multithreaded network application where it
is imperative that no thread cause the entire oz emulator to block.

Unfortunately, as implemented, the "connect" function of the OS module
will block the entire oz-emulator, in particular if the connection
attempt is to a host that does not exist, or to a port on which there is
no service.

"connect" can be made to be non-blocking (at least in UNIX) using a
method described in the book "Unix Network Programming, Vol. 1" by W.
Richard Stevens (pp. 409-422).

However, I'm having trouble implementing this in the OZ code. I'm
certain that the osconnect() function in the file os.cc needs to be
changed to the following:

--- START CODE ---
int osconnect(int s, struct sockaddr *addr, int namelen)
{
  osBlockSignals();

  // MAKE 's' NON-BLOCKING
  int flags = fcntl(s, F_GETFL);
  fcntl(s, F_SETFL, flags | O_NDELAY);

  // "connect" WILL NOT BLOCK
  // "ret" WILL EITHER BE 0, INDICATING SUCCESSFUL connect,
  // OR -1, WITH errno SET TO "EINPROGESS", INDICATING THAT connect
  // IS NOT YET COMPLETE
  int ret = connect(s,addr,namelen);

  // MAKE 's' BLOCKING AGAIN (PROBABLY DOESN'T MATTER)
  fcntl(s, F_SETFL, flags); // MAKE '

  osUnblockSignals();
  return ret;
}
---- END CODE ----

Here's where I'm stuck:

The function that calls osconnect, i.e. "unix_connectInet" in the
"unix.cc" file, needs to be changed to detect errno == EINPROGRESS, and
suspend the current thread until the file descriptor used in the connect
becomes writeable. The needed changes are outlined below:

--- START CODE ---
OZ_BI_define(unix_connectInet,3,0)
{

  // ...

  int ret = osconnect(s,(struct sockaddr *) &addr,sizeof(addr));

  // CONNECT SUCCESSFUL
  if (ret == 0) return PROCEED;

  // CONNECT STILL IN PROGRESS
  if (errno == EINPROGRESS) {

    // SET UP "nbConnectCheck" TO BE CALLED BY OZ SCHEDULER
    // WHEN 's' FILE DESCRIPTOR BECOMES WRITABLE
    OZ_registerWriteHandler(s, nbConnectCheck, 0);

    // HELP! NEED TO SOMEHOW SUSPEND THE CURRENT THREAD
    // AND HAVE IT RESUME WHEN 's' FILE DESCRIPTOR BECOMES WRITABLE.
    // ...
  }

  // BAD CONNECT
  Assert(errno != EINTR);
  RETURN_UNIX_ERROR("connect");

} OZ_BI_end

int nbConnectCheck(int s, void *) {

  // HELP! NEED TO RESUME THREAD THAT WAS SUSPENDED ABOVE.

  int error;

  // ONCE 's' FILE DESCRIPTOR IS WRITABLE, CHECK STATUS WITH getsockopt
  if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &error, sizeof(error) ) <
0 ) {
    RETURN_UNIX_ERROR("connect");
  } else {
    return PROCEED;
  }

}
---- END CODE ----

Am I even on the right track here? Can someone tell me what to do, or
point me in the right direction?

Any help would be *greatly appreciated*.

Thanks

-- Dr. Harmon S. Nine

-
Please send submissions to hackers@mozart-oz.org
and administriva mail to hackers-request@mozart-oz.org.
The Mozart Oz web site is at http://www.mozart-oz.org/.



This archive was generated by hypermail 2b29.