~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/network/socket/qnativesocketengine_unix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
2
**
3
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
4
5
** Contact: Nokia Corporation (qt-info@nokia.com)
5
6
**
6
7
** This file is part of the QtNetwork module of the Qt Toolkit.
7
8
**
8
9
** $QT_BEGIN_LICENSE:LGPL$
9
 
** Commercial Usage
10
 
** Licensees holding valid Qt Commercial licenses may use this file in
11
 
** accordance with the Qt Commercial License Agreement provided with the
12
 
** Software or, alternatively, in accordance with the terms contained in
13
 
** a written agreement between you and Nokia.
 
10
** No Commercial Usage
 
11
** This file contains pre-release code and may not be distributed.
 
12
** You may use this file in accordance with the terms and conditions
 
13
** contained in the Technology Preview License Agreement accompanying
 
14
** this package.
14
15
**
15
16
** GNU Lesser General Public License Usage
16
17
** Alternatively, this file may be used under the terms of the GNU Lesser
20
21
** ensure the GNU Lesser General Public License version 2.1 requirements
21
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22
23
**
23
 
** In addition, as a special exception, Nokia gives you certain
24
 
** additional rights. These rights are described in the Nokia Qt LGPL
25
 
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26
 
** package.
27
 
**
28
 
** GNU General Public License Usage
29
 
** Alternatively, this file may be used under the terms of the GNU
30
 
** General Public License version 3.0 as published by the Free Software
31
 
** Foundation and appearing in the file LICENSE.GPL included in the
32
 
** packaging of this file.  Please review the following information to
33
 
** ensure the GNU General Public License version 3.0 requirements will be
34
 
** met: http://www.gnu.org/copyleft/gpl.html.
35
 
**
36
 
** If you are unsure which license is appropriate for your use, please
37
 
** contact the sales department at http://www.qtsoftware.com/contact.
 
24
** In addition, as a special exception, Nokia gives you certain additional
 
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
 
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
27
**
 
28
** If you have questions regarding the use of this file, please contact
 
29
** Nokia at qt-info@nokia.com.
 
30
**
 
31
**
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
38
38
** $QT_END_LICENSE$
39
39
**
40
40
****************************************************************************/
41
41
 
42
42
//#define QNATIVESOCKETENGINE_DEBUG
43
 
 
44
43
#include "qnativesocketengine_p.h"
 
44
#include "private/qnet_unix_p.h"
45
45
#include "qiodevice.h"
46
46
#include "qhostaddress.h"
47
47
#include "qvarlengtharray.h"
64
64
#include <ctype.h>
65
65
#endif
66
66
 
 
67
#ifdef Q_OS_SYMBIAN // ### TODO: Are these headers right?
 
68
#include <sys/socket.h>
 
69
#include <netinet/in.h>
 
70
#else
 
71
#include <netinet/tcp.h>
 
72
#endif
 
73
 
67
74
QT_BEGIN_NAMESPACE
68
75
 
69
76
#if defined QNATIVESOCKETENGINE_DEBUG
100
107
 
101
108
static void qt_ignore_sigpipe()
102
109
{
 
110
#ifndef Q_NO_POSIX_SIGNALS
103
111
    // Set to ignore SIGPIPE once only.
104
112
    static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
105
113
    if (atom.testAndSetRelaxed(0, 1)) {
108
116
        noaction.sa_handler = SIG_IGN;
109
117
        ::sigaction(SIGPIPE, &noaction, 0);
110
118
    }
 
119
#else
 
120
    // Posix signals are not supported by the underlying platform
 
121
    // so we don't need to ignore sigpipe signal explicitly
 
122
#endif
111
123
}
112
124
 
113
125
/*
126
138
            *addr = tmpAddress;
127
139
#ifndef QT_NO_IPV6IFNAME
128
140
            char scopeid[IFNAMSIZ];
129
 
            if (::if_indextoname(s->a6.sin6_scope_id, scopeid) > 0) {
 
141
            if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
130
142
                addr->setScopeId(QLatin1String(scopeid));
131
143
            } else
132
144
#endif
161
173
    int protocol = AF_INET;
162
174
#endif
163
175
    int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
164
 
    int socket = qt_socket_socket(protocol, type, 0);
 
176
#ifdef Q_OS_SYMBIAN
 
177
    int socket = ::socket(protocol, type, 0);
 
178
#else
 
179
        int socket = qt_safe_socket(protocol, type, 0);
 
180
#endif
165
181
 
166
182
    if (socket <= 0) {
167
183
        switch (errno) {
188
204
 
189
205
    // Ensure that the socket is closed on exec*().
190
206
    ::fcntl(socket, F_SETFD, FD_CLOEXEC);
 
207
 
191
208
    socketDescriptor = socket;
192
209
    return true;
193
210
}
202
219
        return -1;
203
220
 
204
221
    int n = -1;
 
222
    int level = SOL_SOCKET; // default
 
223
 
205
224
    switch (opt) {
206
225
    case QNativeSocketEngine::ReceiveBufferSocketOption:
207
226
        n = SO_RCVBUF;
221
240
    case QNativeSocketEngine::ReceiveOutOfBandData:
222
241
        n = SO_OOBINLINE;
223
242
        break;
 
243
    case QNativeSocketEngine::LowDelayOption:
 
244
        level = IPPROTO_TCP;
 
245
        n = TCP_NODELAY;
 
246
        break;
 
247
    case QNativeSocketEngine::KeepAliveOption:
 
248
        n = SO_KEEPALIVE;
 
249
        break;
224
250
    }
225
251
 
226
252
    int v = -1;
227
253
    QT_SOCKOPTLEN_T len = sizeof(v);
228
 
    if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1)
 
254
    if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
229
255
        return v;
 
256
 
230
257
    return -1;
231
258
}
232
259
 
241
268
        return false;
242
269
 
243
270
    int n = 0;
 
271
    int level = SOL_SOCKET; // default
 
272
 
244
273
    switch (opt) {
245
274
    case QNativeSocketEngine::ReceiveBufferSocketOption:
246
275
        n = SO_RCVBUF;
253
282
        break;
254
283
    case QNativeSocketEngine::NonBlockingSocketOption: {
255
284
        // Make the socket nonblocking.
 
285
#if !defined(Q_OS_VXWORKS)
256
286
        int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
257
287
        if (flags == -1) {
258
288
#ifdef QNATIVESOCKETENGINE_DEBUG
266
296
#endif
267
297
            return false;
268
298
        }
269
 
 
 
299
#else // Q_OS_VXWORKS
 
300
        int onoff = 1;
 
301
#ifdef Q_OS_SYMBIAN
 
302
        if (::ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
 
303
#else
 
304
        if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
 
305
#endif
 
306
#ifdef QNATIVESOCKETENGINE_DEBUG
 
307
            perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
 
308
#endif
 
309
            return false;
 
310
        }
 
311
#endif // Q_OS_VXWORKS
270
312
        return true;
271
313
    }
272
314
    case QNativeSocketEngine::AddressReusable:
273
 
#ifdef SO_REUSEPORT
 
315
#if defined(SO_REUSEPORT) && !defined(Q_OS_SYMBIAN)
274
316
        n = SO_REUSEPORT;
275
317
#else
276
318
        n = SO_REUSEADDR;
281
323
    case QNativeSocketEngine::ReceiveOutOfBandData:
282
324
        n = SO_OOBINLINE;
283
325
        break;
 
326
    case QNativeSocketEngine::LowDelayOption:
 
327
        level = IPPROTO_TCP;
 
328
        n = TCP_NODELAY;
 
329
        break;
 
330
    case QNativeSocketEngine::KeepAliveOption:
 
331
        n = SO_KEEPALIVE;
 
332
        break;
284
333
    }
285
334
 
286
 
    return ::setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0;
 
335
    return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
287
336
}
288
337
 
289
338
bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
290
339
{
 
340
#ifdef QNATIVESOCKETENGINE_DEBUG
 
341
    qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
 
342
#endif
 
343
 
291
344
    struct sockaddr_in sockAddrIPv4;
292
345
    struct sockaddr *sockAddrPtr = 0;
293
346
    QT_SOCKLEN_T sockAddrSize = 0;
325
378
    } else {
326
379
        // unreachable
327
380
    }
328
 
 
329
 
    int connectResult = QT_SOCKET_CONNECT(socketDescriptor, sockAddrPtr, sockAddrSize);
 
381
#ifdef Q_OS_SYMBIAN
 
382
    int connectResult = ::connect(socketDescriptor, sockAddrPtr, sockAddrSize);
 
383
#else
 
384
    int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
 
385
#endif
330
386
    if (connectResult == -1) {
331
387
        switch (errno) {
332
388
        case EISCONN:
430
486
        }
431
487
 
432
488
    int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
 
489
 
433
490
    if (bindResult < 0) {
434
491
        switch(errno) {
435
492
        case EADDRINUSE:
466
523
 
467
524
bool QNativeSocketEnginePrivate::nativeListen(int backlog)
468
525
{
469
 
    if (qt_socket_listen(socketDescriptor, backlog) < 0) {
 
526
#ifdef Q_OS_SYMBIAN
 
527
    if (::listen(socketDescriptor, backlog) < 0) {
 
528
#else
 
529
    if (qt_safe_listen(socketDescriptor, backlog) < 0) {
 
530
#endif
470
531
        switch (errno) {
471
532
        case EADDRINUSE:
472
533
            setError(QAbstractSocket::AddressInUseError,
493
554
 
494
555
int QNativeSocketEnginePrivate::nativeAccept()
495
556
{
496
 
    int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0);
497
 
#if defined (QNATIVESOCKETENGINE_DEBUG)
498
 
    qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
499
 
#endif
500
 
    // Ensure that the socket is closed on exec*()
501
 
    ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
 
557
#ifdef Q_OS_SYMBIAN
 
558
    int acceptedDescriptor = ::accept(socketDescriptor, 0, 0);
 
559
#else
 
560
    int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
 
561
#endif
 
562
    //check if we have vaild descriptor at all
 
563
    if(acceptedDescriptor > 0) {
 
564
        // Ensure that the socket is closed on exec*()
 
565
        ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
 
566
    }
 
567
#ifdef Q_OS_SYMBIAN
 
568
    else {
 
569
        qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0");
 
570
    }
 
571
#endif
 
572
 
502
573
    return acceptedDescriptor;
503
574
}
504
575
 
507
578
    int nbytes = 0;
508
579
    // gives shorter than true amounts on Unix domain sockets.
509
580
    qint64 available = 0;
510
 
    if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
 
581
#ifdef Q_OS_SYMBIAN
 
582
        if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
 
583
#else
 
584
    if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
 
585
#endif
511
586
        available = (qint64) nbytes;
512
587
 
513
588
#if defined (QNATIVESOCKETENGINE_DEBUG)
542
617
    return result;
543
618
}
544
619
 
 
620
#ifdef Q_OS_SYMBIAN
 
621
qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
 
622
{
 
623
    size_t nbytes = 0;
 
624
    ::ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes);
 
625
    return qint64(nbytes-28);
 
626
}
 
627
#else
545
628
qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
546
629
{
547
630
    QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
548
631
    ssize_t recvResult = -1;
 
632
 
549
633
    for (;;) {
550
634
        // the data written to udpMessagePeekBuffer is discarded, so
551
635
        // this function is still reentrant although it might not look
552
636
        // so.
553
637
        recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(),
554
 
                            udpMessagePeekBuffer.size(), MSG_PEEK);
 
638
            udpMessagePeekBuffer.size(), MSG_PEEK);
555
639
        if (recvResult == -1 && errno == EINTR)
556
640
            continue;
557
641
 
567
651
 
568
652
    return qint64(recvResult);
569
653
}
570
 
 
 
654
#endif
571
655
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
572
656
                                                    QHostAddress *address, quint16 *port)
573
657
{
609
693
#if !defined(QT_NO_IPV6)
610
694
    struct sockaddr_in6 sockAddrIPv6;
611
695
    if (host.protocol() == QAbstractSocket::IPv6Protocol) {
612
 
        memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
613
 
        sockAddrIPv6.sin6_family = AF_INET6;
614
 
        sockAddrIPv6.sin6_port = htons(port);
 
696
    memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
 
697
    sockAddrIPv6.sin6_family = AF_INET6;
 
698
    sockAddrIPv6.sin6_port = htons(port);
615
699
 
616
 
        Q_IPV6ADDR tmp = host.toIPv6Address();
617
 
        memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
618
 
        sockAddrSize = sizeof(sockAddrIPv6);
619
 
        sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
 
700
    Q_IPV6ADDR tmp = host.toIPv6Address();
 
701
    memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
 
702
    sockAddrSize = sizeof(sockAddrIPv6);
 
703
    sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
620
704
    } else
621
705
#endif
622
706
    if (host.protocol() == QAbstractSocket::IPv4Protocol) {
623
 
        memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
624
 
        sockAddrIPv4.sin_family = AF_INET;
625
 
        sockAddrIPv4.sin_port = htons(port);
626
 
        sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
627
 
        sockAddrSize = sizeof(sockAddrIPv4);
628
 
        sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
 
707
    memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
 
708
    sockAddrIPv4.sin_family = AF_INET;
 
709
    sockAddrIPv4.sin_port = htons(port);
 
710
    sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
 
711
    sockAddrSize = sizeof(sockAddrIPv4);
 
712
    sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
629
713
    }
630
714
 
631
715
    // ignore the SIGPIPE signal
632
716
    qt_ignore_sigpipe();
633
 
 
634
 
    ssize_t sentBytes;
635
 
    do {
636
 
        sentBytes = ::sendto(socketDescriptor, data, len,
637
 
                             0, sockAddrPtr, sockAddrSize);
638
 
    } while (sentBytes == -1 && errno == EINTR);
 
717
#ifdef Q_OS_SYMBIAN
 
718
    ssize_t sentBytes = ::sendto(socketDescriptor, data, len,
 
719
                                       0, sockAddrPtr, sockAddrSize);
 
720
#else
 
721
    ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
 
722
                                       0, sockAddrPtr, sockAddrSize);
 
723
#endif
639
724
 
640
725
    if (sentBytes < 0) {
641
726
        switch (errno) {
732
817
#if defined (QNATIVESOCKETENGINE_DEBUG)
733
818
    qDebug("QNativeSocketEngine::nativeClose()");
734
819
#endif
 
820
 
 
821
#ifdef Q_OS_SYMBIAN
735
822
    ::close(socketDescriptor);
 
823
#else
 
824
        qt_safe_close(socketDescriptor);
 
825
#endif
736
826
}
737
827
 
738
828
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
746
836
    // of an interrupting signal.
747
837
    ssize_t writtenBytes;
748
838
    do {
749
 
        writtenBytes = ::write(socketDescriptor, data, len);
 
839
#ifdef Q_OS_SYMBIAN
 
840
            writtenBytes = ::write(socketDescriptor, data, len);
 
841
#else
 
842
        writtenBytes = qt_safe_write(socketDescriptor, data, len);
 
843
#endif
 
844
        // writtenBytes = QT_WRITE(socketDescriptor, data, len); ### TODO S60: Should this line be removed or the one above it?
750
845
    } while (writtenBytes < 0 && errno == EINTR);
751
846
 
752
847
    if (writtenBytes < 0) {
788
883
 
789
884
    ssize_t r = 0;
790
885
    do {
 
886
#ifdef Q_OS_SYMBIAN
791
887
        r = ::read(socketDescriptor, data, maxSize);
 
888
#else
 
889
        r = qt_safe_read(socketDescriptor, data, maxSize);
 
890
#endif
792
891
    } while (r == -1 && errno == EINTR);
793
892
 
794
893
    if (r < 0) {
806
905
        case EIO:
807
906
            setError(QAbstractSocket::NetworkError, ReadErrorString);
808
907
            break;
 
908
#ifdef Q_OS_SYMBIAN
 
909
        case EPIPE:
 
910
#endif
809
911
        case ECONNRESET:
 
912
#if defined(Q_OS_VXWORKS)
 
913
        case ESHUTDOWN:
 
914
#endif
810
915
            r = 0;
811
916
            break;
812
917
        default:
833
938
    tv.tv_sec = timeout / 1000;
834
939
    tv.tv_usec = (timeout % 1000) * 1000;
835
940
 
836
 
    QTime timer;
837
 
    timer.start();
 
941
#ifdef Q_OS_SYMBIAN
 
942
    fd_set fdexception;
 
943
    FD_ZERO(&fdexception);
 
944
    FD_SET(socketDescriptor, &fdexception);
 
945
#endif
838
946
 
839
947
    int retval;
840
 
    do {
841
 
        if (selectForRead)
842
 
            retval = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
843
 
        else
844
 
            retval = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
845
 
 
846
 
        if (retval != -1 || errno != EINTR)
847
 
            break;
848
 
 
849
 
        if (timeout > 0) {
850
 
            // recalculate the timeout
851
 
            int t = timeout - timer.elapsed();
852
 
            if (t < 0) {
853
 
                // oops, timeout turned negative?
854
 
                retval = -1;
855
 
                break;
 
948
    if (selectForRead)
 
949
#ifdef Q_OS_SYMBIAN
 
950
        retval = ::select(socketDescriptor + 1, &fds, 0, &fdexception, timeout < 0 ? 0 : &tv);
 
951
#else
 
952
        retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
 
953
#endif
 
954
    else
 
955
#ifdef Q_OS_SYMBIAN
 
956
        retval = ::select(socketDescriptor + 1, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
 
957
#else
 
958
        retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
 
959
#endif
 
960
 
 
961
 
 
962
#ifdef Q_OS_SYMBIAN
 
963
        bool selectForExec = false;
 
964
        if(retval != 0) {
 
965
            if(retval < 0) {
 
966
                qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
856
967
            }
857
 
 
858
 
            tv.tv_sec = t / 1000;
859
 
            tv.tv_usec = (t % 1000) * 1000;
 
968
            selectForExec = FD_ISSET(socketDescriptor, &fdexception);
860
969
        }
861
 
    } while (true);
 
970
        if(selectForExec) {
 
971
            qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected exception for fd %d",
 
972
                    selectForRead, retval, errno, socketDescriptor);
 
973
            }
 
974
#endif
862
975
 
863
976
    return retval;
864
977
}
865
978
 
866
979
int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
867
 
                                      bool *selectForRead, bool *selectForWrite) const
 
980
                       bool *selectForRead, bool *selectForWrite) const
868
981
{
869
982
    fd_set fdread;
870
983
    FD_ZERO(&fdread);
876
989
    if (checkWrite)
877
990
        FD_SET(socketDescriptor, &fdwrite);
878
991
 
 
992
#ifdef Q_OS_SYMBIAN
 
993
    fd_set fdexception;
 
994
    FD_ZERO(&fdexception);
 
995
    FD_SET(socketDescriptor, &fdexception);
 
996
#endif
 
997
 
879
998
    struct timeval tv;
880
999
    tv.tv_sec = timeout / 1000;
881
1000
    tv.tv_usec = (timeout % 1000) * 1000;
882
1001
 
883
 
    QTime timer;
884
 
    timer.start();
885
 
 
886
1002
    int ret;
 
1003
#ifndef Q_OS_SYMBIAN
 
1004
    ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
 
1005
#else
 
1006
    QTime timer;
 
1007
    timer.start();
 
1008
 
887
1009
    do {
888
 
        ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
889
 
        if (ret != -1 || errno != EINTR)
 
1010
        ret = ::select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
 
1011
        bool selectForExec = false;
 
1012
        if(ret != 0) {
 
1013
            if(ret < 0) {
 
1014
                qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
 
1015
            }
 
1016
            selectForExec = FD_ISSET(socketDescriptor, &fdexception);
 
1017
        }
 
1018
        if(selectForExec) {
 
1019
            qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d",
 
1020
                    checkRead, checkWrite, ret, errno, socketDescriptor);
 
1021
            if (checkWrite){
 
1022
                FD_CLR(socketDescriptor, &fdread);
 
1023
                FD_SET(socketDescriptor, &fdwrite);
 
1024
            } else if (checkRead)
 
1025
                FD_SET(socketDescriptor, &fdread);
 
1026
 
 
1027
 
 
1028
            if ((ret == -1) && ( errno == ECONNREFUSED || errno == EPIPE ))
 
1029
                ret = 1;
 
1030
 
 
1031
        }
 
1032
 
 
1033
        if (ret != -1 || errno != EINTR) {
890
1034
            break;
 
1035
        }
891
1036
 
892
1037
        if (timeout > 0) {
893
1038
            // recalculate the timeout
902
1047
            tv.tv_usec = (t % 1000) * 1000;
903
1048
        }
904
1049
    } while (true);
 
1050
#endif
 
1051
 
905
1052
    if (ret <= 0)
906
1053
        return ret;
907
 
 
908
1054
    *selectForRead = FD_ISSET(socketDescriptor, &fdread);
909
1055
    *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
 
1056
 
910
1057
    return ret;
911
1058
}
912
1059