public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-8129] libstdc++: Use strerror_r in std::generic_category()::message(int) [PR110133]
@ 2023-12-06 14:44 Jonathan Wakely
0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-12-06 14:44 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:ca233ac9ba085e2acd385bda6a778684a0c96694
commit r13-8129-gca233ac9ba085e2acd385bda6a778684a0c96694
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Nov 3 13:59:48 2023 +0000
libstdc++: Use strerror_r in std::generic_category()::message(int) [PR110133]
Use strerror_r instead of strerror when available, due to the latter not
being thread-safe. This is complicated by Glibc providing a GNU-specific
strerror_r which is not compatible with POSIX strerror_r, so we need to
dispatch on the return type.
Because we estimate the initial std::string buffer size we might end up
with excess capacity in the returned std::string. We can slightly tweak
the std::system_error constructors to make use of that excess capacity,
so that in some cases we require fewer allocations to construct the
std::system_error::what() string.
libstdc++-v3/ChangeLog:
PR libstdc++/110133
* include/std/system_error (system_error::system_error): Group
arguments so that concatenation can reuse rvalue's capacity.
* src/c++11/system_error.cc (strerror_string): New function.
[_GLIBCXX_HAVE_STRERROR_R] (use_strerror_result): New functions.
(generic_error_category::message): Use strerror_string.
(system_error_category::message): Likewise.
(cherry picked from commit 51f94778b45514992a716b0b2d7a87244e6f0018)
Diff:
---
libstdc++-v3/include/std/system_error | 4 +-
libstdc++-v3/src/c++11/system_error.cc | 81 ++++++++++++++++++++++++++++++----
2 files changed, 75 insertions(+), 10 deletions(-)
diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error
index d71abc9766b..e26472bb0bf 100644
--- a/libstdc++-v3/include/std/system_error
+++ b/libstdc++-v3/include/std/system_error
@@ -563,7 +563,7 @@ namespace __adl_only
: runtime_error(__ec.message()), _M_code(__ec) { }
system_error(error_code __ec, const string& __what)
- : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
+ : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
system_error(error_code __ec, const char* __what)
: runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
@@ -576,7 +576,7 @@ namespace __adl_only
_M_code(__v, __ecat) { }
system_error(int __v, const error_category& __ecat, const string& __what)
- : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
+ : runtime_error(__what + (": " + error_code(__v, __ecat).message())),
_M_code(__v, __ecat) { }
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/src/c++11/system_error.cc b/libstdc++-v3/src/c++11/system_error.cc
index 748eee94168..50033597c06 100644
--- a/libstdc++-v3/src/c++11/system_error.cc
+++ b/libstdc++-v3/src/c++11/system_error.cc
@@ -46,6 +46,77 @@ namespace
{
using std::string;
+#if _GLIBCXX_HAVE_STRERROR_R
+ // Handle the result of POSIX strerror_r.
+ inline std::size_t
+ use_strerror_result(int res, char* buf, std::size_t bufsz,
+ std::size_t& nextbufsz)
+ {
+ if (res == 0) // Success.
+ return std::strlen(buf);
+
+ if (res == ERANGE) // Buffer too small to hold result string.
+ {
+ nextbufsz = 2 * bufsz;
+ return 0;
+ }
+ // else res == EINVAL, unknown error.
+ if (*buf == '\0') // No result string written to buffer.
+ {
+ const char msg[] = "Unknown error";
+ std::memcpy(buf, msg, sizeof(msg) - 1);
+ return sizeof(msg) - 1;
+ }
+ else // An "unknown error" string was already written to the buffer.
+ return std::strlen(buf);
+ }
+
+ // Handle the result of GNU strerror_r.
+ inline std::size_t
+ use_strerror_result(char* res, char* buf, std::size_t bufsz,
+ std::size_t& nextbufsz)
+ {
+ if (res == buf) // Result string written to the buffer.
+ return std::strlen(res);
+
+ // Static result string returned, must be copied to the buffer.
+ std::size_t len = std::strlen(res);
+ if (len <= bufsz)
+ {
+ std::strcpy(buf, res);
+ return len;
+ }
+
+ // Reallocate and try again:
+ nextbufsz = len;
+ return 0;
+ }
+
+ string strerror_string(int err)
+ {
+ // Estimate maximum length of strerror strings (including "Unknown error").
+ // Any excess capacity here can be used by std::system_error constructors
+ // when concatenating strings.
+ std::size_t len = 60;
+ string s;
+ do
+ {
+ s.resize(len);
+ char* p = &s.front();
+ std::size_t n = len;
+ n = use_strerror_result(strerror_r(err, p, n), p, n, len);
+ s.resize(n);
+ }
+ while (s.empty());
+ return s;
+ }
+#else
+ string strerror_string(int err)
+ {
+ return strerror(err); // XXX Not thread-safe.
+ }
+#endif
+
template<typename T>
struct constant_init
{
@@ -66,11 +137,7 @@ namespace
_GLIBCXX_DEFAULT_ABI_TAG
string
message(int i) const final
- {
- // XXX locale issues: how does one get or set loc.
- // _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc)
- return string(strerror(i));
- }
+ { return strerror_string(i); }
// Override this to avoid a virtual call to default_error_condition(i).
bool
@@ -113,9 +180,7 @@ namespace
}
return string("Unknown error code");
#else
- // XXX locale issues: how does one get or set loc.
- // _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc)
- return string(strerror(i));
+ return strerror_string(i);
#endif
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-12-06 14:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-06 14:44 [gcc r13-8129] libstdc++: Use strerror_r in std::generic_category()::message(int) [PR110133] Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).