From 0b757d0c1b6f64d17086621ec692369d37fd62fc Mon Sep 17 00:00:00 2001
From: Thiago Macieira <thiago.macieira@nokia.com>
Date: Thu, 23 Apr 2009 20:07:47 +0200
Subject: Use the safe versions of the network system calls I have just added.

Reviewed-By: ossi
---
 src/corelib/kernel/qcore_unix.cpp               | 63 +++++++++++++++++++++++++
 src/corelib/kernel/qcore_unix_p.h               | 13 ++++-
 src/network/socket/qlocalserver_unix.cpp        |  9 ++--
 src/network/socket/qlocalsocket_p.h             | 37 ---------------
 src/network/socket/qlocalsocket_unix.cpp        |  5 +-
 src/network/socket/qnativesocketengine_unix.cpp |  8 ++--
 src/network/socket/qnet_unix_p.h                |  2 +-
 7 files changed, 88 insertions(+), 49 deletions(-)

diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index ffaf958..2549f77 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -119,3 +119,66 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
 }
 
 QT_END_NAMESPACE
+
+#ifdef Q_OS_LINUX
+// Don't wait for libc to supply the calls we need
+// Make syscalls directly
+
+# if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204
+// glibc 2.4 has syscall(...)
+#  include <sys/syscall.h>
+#  include <asm/unistd.h>
+# else
+// no syscall(...)
+static inline int syscall(...) { errno = ENOSYS; return -1;}
+# endif
+
+# ifndef __NR_dup3
+#  if defined(__i386__)
+#   define __NR_dup3        330
+#   define __NR_pipe2       331
+#  elif defined(__x86_64__)
+#   define __NR_accept4     288
+#   define __NR_dup3        292
+#   define __NR_pipe2       293
+#  elif defined(__ia64__)
+#   define __NR_accept4     -1
+#   define __NR_dup3        1316
+#   define __NR_pipe2       1317
+#  else
+//  set the syscalls to absurd numbers so that they'll cause ENOSYS errors
+#   warning "Please port the pipe2/dup3/accept4 code to this platform"
+#   define __NR_accept4     -1
+#   define __NR_dup3        -1
+#   define __NR_pipe2       -1
+#  endif
+# endif
+
+QT_BEGIN_NAMESPACE
+namespace QtLibcSupplement {
+    int pipe2(int pipes[], int flags)
+    {
+        return syscall(__NR_pipe2, pipes, flags);
+    }
+
+    int dup3(int oldfd, int newfd, int flags)
+    {
+        return syscall(__NR_dup3, oldfd, newfd, flags);
+    }
+
+    int accept4(int s, sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags)
+    {
+# if defined(__NR_socketcall)
+        // This platform uses socketcall() instead of raw syscalls
+        // the SYS_ACCEPT4 number is cross-platform: 18
+        return syscall(__NR_socketcall, 18, &s);
+# else
+        return syscall(__NR_accept4, s, addr, addrlen, flags);
+# endif
+
+        Q_UNUSED(addr); Q_UNUSED(addrlen); Q_UNUSED(flags); // they're actually used
+    }
+}
+QT_END_NAMESPACE
+#endif  // Q_OS_LINUX
+
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 4e3158a..6ae4ff0 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -67,10 +67,21 @@
 #include <errno.h>
 #include <fcntl.h>
 
+struct sockaddr;
+
 QT_BEGIN_NAMESPACE
 
-#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0209
+#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204
+// Linux supports thread-safe FD_CLOEXEC
 # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
+
+namespace QtLibcSupplement {
+    Q_CORE_EXPORT int accept4(int, sockaddr *, QT_SOCKLEN_T *, int flags);
+    Q_CORE_EXPORT int dup3(int oldfd, int newfd, int flags);
+    Q_CORE_EXPORT int pipe2(int pipes[], int flags);
+}
+
+using namespace QtLibcSupplement;
 #else
 # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
 #endif
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index 1cb804a..c2e05cd 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -43,6 +43,7 @@
 #include "qlocalserver_p.h"
 #include "qlocalsocket.h"
 #include "qlocalsocket_p.h"
+#include "qnet_unix_p.h"
 
 #ifndef QT_NO_LOCALSERVER
 
@@ -88,7 +89,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
     serverName = requestedServerName;
 
     // create the unix socket
-    listenSocket = qSocket(PF_UNIX, SOCK_STREAM, 0);
+    listenSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0);
     if (-1 == listenSocket) {
         setError(QLatin1String("QLocalServer::listen"));
         closeServer();
@@ -107,7 +108,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
              fullServerName.toLatin1().size() + 1);
 
     // bind
-    if(-1 == qBind(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
+    if(-1 == QT_SOCKET_BIND(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
         setError(QLatin1String("QLocalServer::listen"));
         // if address is in use already, just close the socket, but do not delete the file
         if(errno == EADDRINUSE)
@@ -120,7 +121,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
     }
 
     // listen for connections
-    if (-1 == qListen(listenSocket, 50)) {
+    if (-1 == qt_safe_listen(listenSocket, 50)) {
         setError(QLatin1String("QLocalServer::listen"));
         closeServer();
         listenSocket = -1;
@@ -172,7 +173,7 @@ void QLocalServerPrivate::_q_onNewConnection()
 
     ::sockaddr_un addr;
     QT_SOCKLEN_T length = sizeof(sockaddr_un);
-    int connectedSocket = qAccept(listenSocket, (sockaddr *)&addr, &length);
+    int connectedSocket = qt_safe_accept(listenSocket, (sockaddr *)&addr, &length);
     if(-1 == connectedSocket) {
         setError(QLatin1String("QLocalSocket::activated"));
         closeServer();
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index 24b5dd6..bdbba42 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -74,43 +74,6 @@
 
 QT_BEGIN_NAMESPACE
 
-#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
-static inline int qSocket(int af, int socketype, int proto)
-{
-    int ret;
-    while((ret = qt_socket_socket(af, socketype, proto)) == -1 && errno == EINTR){}
-    return ret;
-}
-
-static inline int qBind(int fd, const sockaddr *sa, int len)
-{
-    int ret;
-    while((ret = QT_SOCKET_BIND(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){}
-    return ret;
-}
-
-static inline int qConnect(int fd, const sockaddr *sa, int len)
-{
-    int ret;
-    while((ret = QT_SOCKET_CONNECT(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){}
-    return ret;
-}
-
-static inline int qListen(int fd, int backlog)
-{
-    int ret;
-    while((ret = qt_socket_listen(fd, backlog)) == -1 && errno == EINTR){}
-    return ret;
-}
-
-static inline int qAccept(int fd, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
-{
-    int ret;
-    while((ret = qt_socket_accept(fd, addr, addrlen)) == -1 && errno == EINTR){}
-    return ret;
-}
-#endif //#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
-
 #if !defined(Q_OS_WIN) || defined(QT_LOCALSOCKET_TCP)
 class QLocalUnixSocket : public QTcpSocket
 {
diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp
index 41dac3c..d038794 100644
--- a/src/network/socket/qlocalsocket_unix.cpp
+++ b/src/network/socket/qlocalsocket_unix.cpp
@@ -41,6 +41,7 @@
 
 #include "qlocalsocket.h"
 #include "qlocalsocket_p.h"
+#include "qnet_unix_p.h"
 
 #ifndef QT_NO_LOCALSOCKET
 
@@ -232,7 +233,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
     }
 
     // create the socket
-    if (-1 == (d->connectingSocket = qSocket(PF_UNIX, SOCK_STREAM, 0))) {
+    if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0))) {
         d->errorOccurred(UnsupportedSocketOperationError,
                         QLatin1String("QLocalSocket::connectToServer"));
         return;
@@ -282,7 +283,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
     }
     ::memcpy(name.sun_path, connectingPathName.toLatin1().data(),
              connectingPathName.toLatin1().size() + 1);
-    if (-1 == qConnect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
+    if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
         QString function = QLatin1String("QLocalSocket::connectToServer");
         switch (errno)
         {
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 6eafe05..0c1fa19 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -42,7 +42,7 @@
 //#define QNATIVESOCKETENGINE_DEBUG
 
 #include "qnativesocketengine_p.h"
-#include "private/qcore_unix_p.h"
+#include "private/qnet_unix_p.h"
 #include "qiodevice.h"
 #include "qhostaddress.h"
 #include "qvarlengtharray.h"
@@ -162,7 +162,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
     int protocol = AF_INET;
 #endif
     int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
-    int socket = qt_socket_socket(protocol, type, 0);
+    int socket = qt_safe_socket(protocol, type, 0);
 
     if (socket <= 0) {
         switch (errno) {
@@ -467,7 +467,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
 
 bool QNativeSocketEnginePrivate::nativeListen(int backlog)
 {
-    if (qt_socket_listen(socketDescriptor, backlog) < 0) {
+    if (qt_safe_listen(socketDescriptor, backlog) < 0) {
         switch (errno) {
         case EADDRINUSE:
             setError(QAbstractSocket::AddressInUseError,
@@ -494,7 +494,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
 
 int QNativeSocketEnginePrivate::nativeAccept()
 {
-    int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0);
+    int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
 #if defined (QNATIVESOCKETENGINE_DEBUG)
     qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
 #endif
diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h
index 5256131..80a4c58 100644
--- a/src/network/socket/qnet_unix_p.h
+++ b/src/network/socket/qnet_unix_p.h
@@ -100,7 +100,7 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add
     Q_ASSERT((flags & ~O_NONBLOCK) == 0);
 
     register int fd;
-#if 0    // no released version of glibc contains accept4 yet
+#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC
     // use accept4
     int sockflags = SOCK_CLOEXEC;
     if (flags & O_NONBLOCK)
-- 
cgit v0.12