This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] Final fix for libstdc++/13731
- From: Paolo Carlini <pcarlini at suse dot de>
- To: "'gcc-patches at gcc dot gnu dot org'" <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 12 Feb 2004 19:28:57 +0100
- Subject: [v3] Final fix for libstdc++/13731
Hi,
the below fixes the second part (unsafe writev). I'm committing to
mainline only but this is a regression from 3.3, therefore after
some days of testing both patches will go to 3_4-branch too.
Tested x86-linux.
Paolo.
///////////
2004-02-12 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/13731 (final part: writev)
* config/io/basic_file_stdio.cc (__gnu_internal::xwrite):
New, a wrapper around writev() handling partial writes.
(__basic_file<char>::xwrite): Move to __gnu_internal and make
static.
(__basic_file<char>::xsputn): Update call.
(__basic_file<char>::xsputn_2): Likewise.
* config/io/basic_file_stdio.h (__basic_file<char>::write):
Don't declare, now static.
diff -prN libstdc++-v3-orig/config/io/basic_file_stdio.cc libstdc++-v3/config/io/basic_file_stdio.cc
*** libstdc++-v3-orig/config/io/basic_file_stdio.cc Thu Feb 12 01:01:03 2004
--- libstdc++-v3/config/io/basic_file_stdio.cc Thu Feb 12 12:53:29 2004
*************** namespace __gnu_internal
*** 105,110 ****
--- 105,164 ----
default: return 0; // invalid
}
}
+
+ // Wrapper handling partial write.
+ static std::streamsize
+ xwrite(int __fd, const char* __s, std::streamsize __n)
+ {
+ std::streamsize __nleft = __n;
+ while (__nleft > 0)
+ {
+ const std::streamsize __ret = write(__fd, __s, __nleft);
+ if (__ret == -1L && errno == EINTR)
+ continue;
+ else if (__ret == -1L)
+ break;
+ __nleft -= __ret;
+ __s += __ret;
+ }
+ return __n - __nleft;
+ }
+
+ #ifdef _GLIBCXX_HAVE_WRITEV
+ // Wrapper handling partial writev.
+ static std::streamsize
+ xwritev(int __fd, const char* __s1, std::streamsize __n1,
+ const char* __s2, std::streamsize __n2)
+ {
+ std::streamsize __ret;
+
+ struct iovec __iov[2];
+ __iov[0].iov_base = const_cast<char*>(__s1);
+ __iov[0].iov_len = __n1;
+ __iov[1].iov_base = const_cast<char*>(__s2);
+ __iov[1].iov_len = __n2;
+
+ do
+ __ret = writev(__fd, __iov, 2);
+ while (__ret == -1L && errno == EINTR);
+
+ if (__ret == -1L)
+ __ret = 0;
+ else if (__ret < __n1 + __n2)
+ {
+ if (__ret >= __n1)
+ {
+ const std::streamsize __off = __ret - __n1;
+ __ret += xwrite(__fd, __s2 + __off, __n2 - __off);
+ }
+ else
+ __ret += xwritev(__fd, __s1 + __ret, __n1 - __ret,
+ __s2, __n2);
+ }
+
+ return __ret;
+ }
+ #endif
} // namespace __gnu_internal
namespace std
*************** namespace std
*** 201,227 ****
return __ret;
}
- // Wrapper handling partial write.
- streamsize
- __basic_file<char>::xwrite(const char* __s, streamsize __n)
- {
- streamsize __nleft = __n;
- while (__nleft > 0)
- {
- const streamsize __ret = write(this->fd(), __s, __nleft);
- if (__ret == -1L && errno == EINTR)
- continue;
- else if (__ret == -1L)
- break;
- __nleft -= __ret;
- __s += __ret;
- }
- return __n - __nleft;
- }
-
streamsize
__basic_file<char>::xsputn(const char* __s, streamsize __n)
! { return __basic_file<char>::xwrite(__s, __n); }
streamsize
__basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
--- 255,263 ----
return __ret;
}
streamsize
__basic_file<char>::xsputn(const char* __s, streamsize __n)
! { return __gnu_internal::xwrite(this->fd(), __s, __n); }
streamsize
__basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
*************** namespace std
*** 229,249 ****
{
streamsize __ret = 0;
#ifdef _GLIBCXX_HAVE_WRITEV
! struct iovec __iov[2];
! __iov[0].iov_base = const_cast<char*>(__s1);
! __iov[0].iov_len = __n1;
! __iov[1].iov_base = const_cast<char*>(__s2);
! __iov[1].iov_len = __n2;
!
! do
! __ret = writev(this->fd(), __iov, 2);
! while (__ret == -1L && errno == EINTR);
#else
if (__n1)
! __ret = __basic_file<char>::xwrite(__s1, __n1);
if (__ret == __n1)
! __ret += __basic_file<char>::xwrite(__s2, __n2);
#endif
return __ret;
}
--- 265,277 ----
{
streamsize __ret = 0;
#ifdef _GLIBCXX_HAVE_WRITEV
! __ret = __gnu_internal::xwritev(this->fd(), __s1, __n1, __s2, __n2);
#else
if (__n1)
! __ret = __gnu_internal::xwrite(this->fd(), __s1, __n1);
if (__ret == __n1)
! __ret += __gnu_internal::xwrite(this->fd(), __s2, __n2);
#endif
return __ret;
}
diff -prN libstdc++-v3-orig/config/io/basic_file_stdio.h libstdc++-v3/config/io/basic_file_stdio.h
*** libstdc++-v3-orig/config/io/basic_file_stdio.h Wed Feb 11 17:59:49 2004
--- libstdc++-v3/config/io/basic_file_stdio.h Thu Feb 12 12:51:55 2004
*************** namespace std
*** 84,92 ****
~__basic_file();
streamsize
- xwrite(const char* __s, streamsize __n);
-
- streamsize
xsputn(const char* __s, streamsize __n);
streamsize
--- 84,89 ----