From kde-core-devel Mon Nov 10 02:45:23 2008 From: Daniel Winter Date: Mon, 10 Nov 2008 02:45:23 +0000 To: kde-core-devel Subject: Qt patch: Redo select on EINTR "error" (QLocalSocket) Message-Id: <200811100345.24505.dw () danielwinter ! de> X-MARC-Message: https://marc.info/?l=kde-core-devel&m=122628518123927 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_EB6FJpoUY80f+l5" --Boundary-00=_EB6FJpoUY80f+l5 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 --Boundary-00=_EB6FJpoUY80f+l5 Content-Type: text/x-patch; charset="UTF-8"; name="restart-select-on-EINTR.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="restart-select-on-EINTR.diff" 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; --Boundary-00=_EB6FJpoUY80f+l5--