--- 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"