[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Qt patch: Redo select on EINTR "error" (QLocalSocket)
From:       Daniel Winter <dw () danielwinter ! de>
Date:       2008-11-10 2:45:23
Message-ID: 200811100345.24505.dw () danielwinter ! de
[Download RAW message or body]

Hi,

while trying to fix a bug in Soprano/Nepomuk I found out, that it is in fact a 
bug in Qt. (With the help of Marcos Dione (StyXman in IRC) who wrote the 
attached patch).

Qt is doing select to wait for the Socket being ready to read/write from/to 
but doesn't handle the case where it gets interrupted by an unix signal. Qt 
just handles that as any other Socket error (thoug it isn't really an error) 
and closes the socket instead of just redo the select.    I already made a bug 
report at trolltech.com.

Can someone please take a look at the patch ( I think it  is not really 
optimal as it is, but it fixes the issue with Soprano )?  What needs to be done 
to get it in the qt-copy patch set?

DanielW

["restart-select-on-EINTR.diff" (text/x-patch)]

Index: qt-copy/src/network/socket/qnativesocketengine_unix.cpp
===================================================================
--- qt-copy/src/network/socket/qnativesocketengine_unix.cpp	(revision 881517)
+++ qt-copy/src/network/socket/qnativesocketengine_unix.cpp	(working copy)
@@ -861,13 +861,25 @@
     FD_SET(socketDescriptor, &fds);
 
     struct timeval tv;
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
+    int left= timeout;
+    clock_t start, stop;
 
-    if (selectForRead)
-        return select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
-    else
-        return select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
+    int s;
+    do {
+        tv.tv_sec = left / 1000;
+        tv.tv_usec = (left % 1000) * 1000;
+
+        start = clock();
+        if (selectForRead) {
+            s = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
+        } else {
+            s = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
+        }
+        stop = clock();
+        // calcule how much we should wait
+        // instead of using the same value again
+        left = left - (stop-start)/CLOCKS_PER_SEC*1000;
+    } while (s == -1 && errno == EINTR);
 }
 
 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
@@ -884,10 +896,22 @@
         FD_SET(socketDescriptor, &fdwrite);
 
     struct timeval tv;
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
+    int left= timeout;
+    clock_t start, stop;
 
-    int ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
+    int ret;
+    do {
+        tv.tv_sec = left / 1000;
+        tv.tv_usec = (left % 1000) * 1000;
+
+        start = clock();
+        ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
+        stop = clock();
+        // calcule how much we should wait
+        // instead of using the same value again
+        left = left - (stop-start)/CLOCKS_PER_SEC*1000;
+    } while (ret == -1 && errno == EINTR);
+
     if (ret <= 0)
         return ret;
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic