[MLton] Socket.connectNB on NetBSD

Jesper Louis Andersen jlouis@mongers.org
Thu, 27 Nov 2003 02:49:03 +0100


Quoting Stephen Weeks (sweeks@sweeks.com):

> The man pages for Linux, NetBSD, and SunOS all agree that connect
> should return -1 with EINPROGRESS when the socket is nonblocking and
> the connect cannot be made.  Perhaps the problem is that the fcntl
> stuff isn't working right and the socket is not correctly being marked
> nonblocking?

First idea: break down the code to plain C and see what happens:

+--------------
#include <stdio.h>
#include <stdlib.h>

#include <assert.h>

#include <errno.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>

int
main(int argc, char **argv)
{
	int sock, sock2, socklen, res;
	struct sockaddr_in sa, sa2;

	/* Allocate a socket */
	sock = socket(PF_INET, SOCK_STREAM, 0);

	sa.sin_family = AF_INET;
	sa.sin_port = 0;
	sa.sin_addr.s_addr = INADDR_ANY;

	
	if (bind(sock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
		printf("ARGH\n");
		return EXIT_FAILURE;
	}

	if (listen(sock, 5) == -1) {
		printf("ARGH2\n");
		return EXIT_FAILURE;
	}

	socklen = sizeof(sa2);
	if (getsockname(sock, (struct sockaddr *) &sa2, &socklen) == -1) {
		printf("ARGH3\n");
		return EXIT_FAILURE;
	}
		
	sock2 = socket(PF_INET, SOCK_STREAM, 0);

	/* This is crude and incorrect, but what the f... */
	fcntl(sock2, F_SETFL, O_NONBLOCK);

	/* try to connect */
	res = connect(sock2, (struct sockaddr *) &sa2, socklen);
	if (res == 0) {
		printf("0\n");
		return EXIT_SUCCESS;
	} else if (res == -1) {
		printf("-1 ... errno: %d\n", errno);
		return EXIT_FAILURE;
	} else {
		printf("ARGH4\n");
		return EXIT_FAILURE;
	}

	assert(0); /* Not reached */
}
+-----------------------------

This succeeds on NetBSD but fails on the university's Redhat 7.3 boxen. The errno is set at
EINPROGRESS (115 in Linux). I agree it should fail. Now for the fun part:

Adding a line which sets sa2.sin_addr.s_addr = INADDR_LOOPBACK gives the intended failure
behaviour on NetBSD. That said I have had absolutely none socket experience up
until now where I have begun reading about it since I want this bug fixed. I am
too tired to continue with the problem now, but I will dig further into socket
programming and the problem in question the coming days.

There is also the possibility to ask the NetBSD team as to why it gives us the answer
it does. I expect them to be much better at reading C source like the above than source
generated by the MLton compilers C backend (or similiar, heh). 

At least I have learned a lot about unix sockets programming the last 2 days.

-- 
j.