summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qcore_unix.cpp63
-rw-r--r--src/corelib/kernel/qcore_unix_p.h13
-rw-r--r--src/network/socket/qlocalserver_unix.cpp9
-rw-r--r--src/network/socket/qlocalsocket_p.h37
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp5
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp8
-rw-r--r--src/network/socket/qnet_unix_p.h2
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)