summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/unix/cloexec/cloexec.cpp49
-rw-r--r--config.tests/unix/cloexec/cloexec.pro3
-rwxr-xr-xconfigure10
-rw-r--r--src/corelib/kernel/qcore_unix_p.h60
-rw-r--r--src/network/socket/qnet_unix_p.h18
5 files changed, 87 insertions, 53 deletions
diff --git a/config.tests/unix/cloexec/cloexec.cpp b/config.tests/unix/cloexec/cloexec.cpp
new file mode 100644
index 0000000000..3f127d8d3f
--- /dev/null
+++ b/config.tests/unix/cloexec/cloexec.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Intel Corporation.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the configuration module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define _GNU_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int main()
+{
+ int pipes[2];
+ (void) pipe2(pipes, O_CLOEXEC | O_NONBLOCK);
+ (void) fcntl(0, F_DUPFD_CLOEXEC, 0);
+ (void) dup3(0, 3, O_CLOEXEC);
+ (void) accept4(0, 0, 0, SOCK_CLOEXEC | SOCK_NONBLOCK);
+ return 0;
+}
diff --git a/config.tests/unix/cloexec/cloexec.pro b/config.tests/unix/cloexec/cloexec.pro
new file mode 100644
index 0000000000..bc735f9b1f
--- /dev/null
+++ b/config.tests/unix/cloexec/cloexec.pro
@@ -0,0 +1,3 @@
+SOURCES = cloexec.cpp
+CONFIG -= qt
+QT =
diff --git a/configure b/configure
index a53eaff16d..864b747919 100755
--- a/configure
+++ b/configure
@@ -728,6 +728,7 @@ CFG_IPV6IFNAME=auto
CFG_GETIFADDRS=auto
CFG_INOTIFY=auto
CFG_EVENTFD=auto
+CFG_CLOEXEC=no
CFG_RPATH=yes
CFG_FRAMEWORK=auto
CFG_USE_GOLD_LINKER=auto
@@ -5869,6 +5870,11 @@ if [ "$CFG_GETIFADDRS" != "no" ]; then
fi
fi
+# find if the platform provides thread-safe CLOEXEC support
+if compileTest unix/cloexec; then
+ CFG_CLOEXEC=yes
+fi
+
# detect OpenSSL
if [ "$CFG_OPENSSL" != "no" ]; then
if compileTest unix/openssl "OpenSSL"; then
@@ -6147,6 +6153,9 @@ fi
if [ "$CFG_EVENTFD" = "yes" ]; then
QT_CONFIG="$QT_CONFIG eventfd"
fi
+if [ "$CFG_CLOEXEC" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG threadsafe-cloexec"
+fi
if [ "$CFG_LIBJPEG" = "no" ]; then
CFG_JPEG="no"
elif [ "$CFG_LIBJPEG" = "system" ]; then
@@ -6627,6 +6636,7 @@ QMakeVar set sql-plugins "$SQL_PLUGINS"
[ "$CFG_GETIFADDRS" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_GETIFADDRS"
[ "$CFG_INOTIFY" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_INOTIFY"
[ "$CFG_EVENTFD" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EVENTFD"
+[ "$CFG_CLOEXEC" = "yes" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_THREADSAFE_CLOEXEC=1"
[ "$CFG_NIS" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_NIS"
[ "$CFG_OPENSSL" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_OPENSSL"
[ "$CFG_OPENSSL" = "linked" ]&& QCONFIG_FLAGS="$QCONFIG_FLAGS QT_LINKED_OPENSSL"
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index ce8d9f6d65..c744873fce 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -67,24 +67,6 @@
struct sockaddr;
-#if defined(Q_OS_LINUX) && defined(O_CLOEXEC)
-# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
-QT_BEGIN_NAMESPACE
-namespace QtLibcSupplement {
- inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int)
- { errno = ENOSYS; return -1; }
- inline int dup3(int, int, int)
- { errno = ENOSYS; return -1; }
- inline int pipe2(int [], int )
- { errno = ENOSYS; return -1; }
-}
-QT_END_NAMESPACE
-using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement);
-
-#else
-# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
-#endif
-
#define EINTR_LOOP(var, cmd) \
do { \
var = cmd; \
@@ -181,16 +163,12 @@ static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
{
Q_ASSERT((flags & ~O_NONBLOCK) == 0);
- int ret;
-#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
+#ifdef QT_THREADSAFE_CLOEXEC
// use pipe2
flags |= O_CLOEXEC;
- ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR
- if (ret == 0 || errno != ENOSYS)
- return ret;
-#endif
-
- ret = ::pipe(pipefd);
+ return ::pipe2(pipefd, flags); // pipe2 is documented not to return EINTR
+#else
+ int ret = ::pipe(pipefd);
if (ret == -1)
return -1;
@@ -204,6 +182,7 @@ static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
}
return 0;
+#endif
}
#endif // Q_OS_VXWORKS
@@ -213,22 +192,19 @@ static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC
{
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
- int ret;
#ifdef F_DUPFD_CLOEXEC
- // use this fcntl
- if (flags & FD_CLOEXEC) {
- ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast);
- if (ret != -1 || errno != EINVAL)
- return ret;
- }
-#endif
-
+ int cmd = F_DUPFD;
+ if (flags & FD_CLOEXEC)
+ cmd = F_DUPFD_CLOEXEC;
+ return ::fcntl(oldfd, cmd, atleast);
+#else
// use F_DUPFD
- ret = ::fcntl(oldfd, F_DUPFD, atleast);
+ int ret = ::fcntl(oldfd, F_DUPFD, atleast);
if (flags && ret != -1)
::fcntl(ret, F_SETFD, flags);
return ret;
+#endif
}
// don't call dup2
@@ -238,14 +214,11 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
int ret;
-#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
+#ifdef QT_THREADSAFE_CLOEXEC
// use dup3
- if (flags & FD_CLOEXEC) {
- EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC));
- if (ret == 0 || errno != ENOSYS)
- return ret;
- }
-#endif
+ EINTR_LOOP(ret, ::dup3(oldfd, newfd, flags ? O_CLOEXEC : 0));
+ return ret;
+#else
EINTR_LOOP(ret, ::dup2(oldfd, newfd));
if (ret == -1)
return -1;
@@ -253,6 +226,7 @@ static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
if (flags)
::fcntl(newfd, F_SETFD, flags);
return 0;
+#endif
}
static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h
index cd118afd63..a5a87fc7c1 100644
--- a/src/network/socket/qnet_unix_p.h
+++ b/src/network/socket/qnet_unix_p.h
@@ -77,15 +77,13 @@ static inline int qt_safe_socket(int domain, int type, int protocol, int flags =
Q_ASSERT((flags & ~O_NONBLOCK) == 0);
int fd;
-#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+#ifdef QT_THREADSAFE_CLOEXEC
int newtype = type | SOCK_CLOEXEC;
if (flags & O_NONBLOCK)
newtype |= SOCK_NONBLOCK;
fd = ::socket(domain, newtype, protocol);
- if (fd != -1 || errno != EINVAL)
- return fd;
-#endif
-
+ return fd;
+#else
fd = ::socket(domain, type, protocol);
if (fd == -1)
return -1;
@@ -97,6 +95,7 @@ static inline int qt_safe_socket(int domain, int type, int protocol, int flags =
::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
return fd;
+#endif
}
// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
@@ -105,16 +104,14 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add
Q_ASSERT((flags & ~O_NONBLOCK) == 0);
int fd;
-#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+#ifdef QT_THREADSAFE_CLOEXEC
// use accept4
int sockflags = SOCK_CLOEXEC;
if (flags & O_NONBLOCK)
sockflags |= SOCK_NONBLOCK;
fd = ::accept4(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen), sockflags);
- if (fd != -1 || !(errno == ENOSYS || errno == EINVAL))
- return fd;
-#endif
-
+ return fd;
+#else
fd = ::accept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen));
if (fd == -1)
return -1;
@@ -126,6 +123,7 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add
::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
return fd;
+#endif
}
// UnixWare 7 redefines listen -> _listen