--- smalltalk-3.1.orig/configure.ac
+++ smalltalk-3.1/configure.ac
@@ -298,7 +298,7 @@
 	symlink mkdtemp)
 AC_CHECK_FUNCS_ONCE(gethostname memcpy memmove sighold uname usleep lstat \
 	grantpt popen getrusage gettimeofday fork strchr utimes utime readlink \
-	sigsetmask alarm select mprotect madvise waitpid \
+	sigsetmask alarm select mprotect madvise waitpid accept4 \
 	setsid spawnl nanosleep pread pwrite _NSGetExecutablePath)
 
 GST_FUNC_LRINT
--- smalltalk-3.1.orig/lib-src/socketx.h
+++ smalltalk-3.1/lib-src/socketx.h
@@ -93,7 +93,7 @@
 }
 
 #define FD_TO_SOCKET(fd)   ((SOCKET) _get_osfhandle ((fd)))
-#define SOCKET_TO_FD(fh)   (_open_osfhandle ((HANDLE) (fh), O_RDWR | O_BINARY))
+#define SOCKET_TO_FD(fh)   (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
 
 #undef close
 #define close		   win_close
--- smalltalk-3.1.orig/packages/sockets/sockets.c
+++ smalltalk-3.1/packages/sockets/sockets.c
@@ -245,29 +245,55 @@
 
 
 
-static int
-mySocket (int domain, int type, int protocol)
+#if defined SOCK_CLOEXEC && !defined __MSVCRT__
+/* 0 = unknown, 1 = yes, -1 = no.  */
+static mst_Boolean have_sock_cloexec;
+
+/* Return 0 if the operation failed and an error can be returned
+   by the caller.  */
+static inline int
+check_have_sock_cloexec (int fh, int expected_errno)
 {
-  int fd;
-#if defined __MSVCRT__
-  SOCKET fh = socket (domain, type, protocol);
-  fd = SOCKET_TO_FD (fh);
-
-  /* Do not do FD_CLOEXEC under MinGW.  */
-  SetHandleInformation (fh, HANDLE_FLAG_INHERIT, 0);
+  if (have_sock_cloexec == 0 && (fh >= 0 || errno == expected_errno))
+    have_sock_cloexec = (fh >= 0 ? 1 : -1);
+  return (have_sock_cloexec != 0);
+}
+#endif
 
-#elif defined SOCK_CLOEXEC
-  fd = socket (domain, type | SOCK_CLOEXEC, protocol);
+static void
+socket_set_cloexec (SOCKET fh)
+{
+  if (fh == SOCKET_ERROR)
+    return;
 
+#if defined __MSVCRT__
+  /* Do not do FD_CLOEXEC under MinGW.  */
+  SetHandleInformation ((HANDLE) fh, HANDLE_FLAG_INHERIT, 0);
 #else
-  fd = socket (domain, type, protocol);
-#ifdef FD_CLOEXEC
-  if (fd != -1)
-    fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
+  fcntl (fh, F_SETFD, fcntl (fh, F_GETFD, 0) | FD_CLOEXEC);
 #endif
+}
+
+static int
+mySocket (int domain, int type, int protocol)
+{
+  SOCKET fh = SOCKET_ERROR;
+
+#if defined SOCK_CLOEXEC && !defined __MSVCRT__
+  if (have_sock_cloexec >= 0)
+    {
+      fh = socket (domain, type | SOCK_CLOEXEC, protocol);
+      if (!check_have_sock_cloexec (fh, EINVAL))
+	return -1;
+    }
 #endif
+  if (fh == SOCKET_ERROR)
+    {
+      fh = socket (domain, type, protocol);
+      socket_set_cloexec (fh);
+    }
 
-  return fd;
+  return fh == SOCKET_ERROR ? -1 : SOCKET_TO_FD (fh);
 }
 
 
@@ -287,10 +313,12 @@
 }
 
 /* Same as connect, but forces the socket to be in non-blocking mode */
-static void
+static int
 myConnect (int fd, struct sockaddr *sockaddr, int len)
 {
   SOCKET sock = FD_TO_SOCKET (fd);
+  int rc;
+
 #ifdef __MSVCRT__
   unsigned long iMode = 1;
   ioctlsocket (sock, FIONBIO, &iMode);
@@ -303,16 +331,35 @@
 #endif
   
   fix_sockaddr (sockaddr);
-  connect (sock, sockaddr, len);
-  if (is_socket_error (EINPROGRESS) || is_socket_error (EWOULDBLOCK))
-    errno = 0;
+  rc = connect (sock, sockaddr, len);
+  if (rc == 0 || is_socket_error (EINPROGRESS) || is_socket_error (EWOULDBLOCK))
+    {
+      errno = 0;
+      return 0;
+    }
+  else
+    return -1;
 }
 
 static int
 myAccept (int fd, struct sockaddr *addr, int *addrlen)
 {
-  SOCKET r = accept (FD_TO_SOCKET (fd), addr, addrlen);
-  return r == SOCKET_ERROR ? -1 : SOCKET_TO_FD (r);
+  SOCKET fh = SOCKET_ERROR;
+#if defined SOCK_CLOEXEC && defined HAVE_ACCEPT4 && !defined __MSVCRT__
+  if (have_sock_cloexec >= 0)
+    {
+      fh = accept4 (FD_TO_SOCKET (fd), addr, addrlen, SOCK_CLOEXEC);
+      if (!check_have_sock_cloexec (fh, ENOSYS))
+	return -1;
+    }
+#endif
+  if (fh == SOCKET_ERROR)
+    {
+      fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
+      socket_set_cloexec (fh);
+    }
+
+  return fh == SOCKET_ERROR ? -1 : SOCKET_TO_FD (fh);
 }
 
 static int
--- smalltalk-3.1.orig/packages/sockets/AbstractSocketImpl.st
+++ smalltalk-3.1/packages/sockets/AbstractSocketImpl.st
@@ -75,7 +75,7 @@
 		    create: addressClass protocolFamily
 		    type: self socketType
 		    protocol: self protocol.
-	File checkError.
+	descriptor < 0 ifTrue: [ File checkError ].
 	^self on: descriptor
     ]
 
@@ -93,6 +93,7 @@
 		    accept: fd
 		    peer: peer
 		    addrLen: addrLen.
+        newFD < 0 ifTrue: [ File checkError: self soError ].
 	^(implementationClass on: newFD)
 	    hasBeenBound;
 	    hasBeenConnectedTo: peer;
@@ -108,11 +109,10 @@
 	addr := ipAddress port: port.
 	
 	(fd := self fd) isNil ifTrue: [ ^self ].
-	[self 
+	[(self 
 	    bind: fd
 	    to: addr
-	    addrLen: addr size.
-	File checkError] 
+	    addrLen: addr size) < 0 ifTrue: [File checkError: self soError] ]
 		ifCurtailed: [self close].
 	self isOpen ifTrue: [self hasBeenBound]
     ]
@@ -519,11 +519,10 @@
 	addr := ipAddress port: port.
 	
 	[(fd := self fd) isNil ifTrue: [ ^self ].
-	self 
+	(self 
 	    connect: fd
 	    to: addr
-	    addrLen: addr size.
-	File checkError] 
+	    addrLen: addr size) < 0 ifTrue: [File checkError: self soError] ]
 		ifCurtailed: [self close].
 
 	"connect does not block, so wait for"
