Improve gethostbyname_r use in art::JDWP::JdwpSocketState::Establish.
Try a range of values for the work buffer size, instead of
using a fixed size.
Also, turn a couple of constants defined as macros into
constexprs.
Change-Id: I2354bfb51935bb0cad775c13d6cae06902b4a934
diff --git a/runtime/jdwp/jdwp_socket.cc b/runtime/jdwp/jdwp_socket.cc
index 1bc58ac..8d59cc1 100644
--- a/runtime/jdwp/jdwp_socket.cc
+++ b/runtime/jdwp/jdwp_socket.cc
@@ -30,13 +30,29 @@
#include "base/stringprintf.h"
#include "jdwp/jdwp_priv.h"
-#define kBasePort 8000
-#define kMaxPort 8040
-
namespace art {
namespace JDWP {
+static constexpr uint16_t kBasePort = 8000;
+static constexpr uint16_t kMaxPort = 8040;
+
+// Initial size of the work buffer used in gethostbyname_r.
+//
+// The call to gethostbyname_r below requires a user-allocated buffer,
+// the size of which depends on the system. The initial implementation
+// used to use a 128-byte buffer, but that was not enough on some
+// systems (maybe because of IPv6), causing failures in JDWP host
+// testing; thus it was increased to 256.
+//
+// However, we should not use a fixed size: gethostbyname_r's
+// documentation states that if the work buffer is too small (i.e. if
+// gethostbyname_r returns `ERANGE`), then the function should be
+// called again with a bigger buffer. Which we do now, starting with
+// an initial 256-byte buffer, and doubling it until gethostbyname_r
+// accepts this size.
+static constexpr size_t kInitialAuxBufSize = 256;
+
/*
* JDWP network state.
*
@@ -276,15 +292,16 @@
*/
#if defined(__linux__)
hostent he;
- // The size of the work buffer used in the gethostbyname_r call
- // below. It used to be 128, but this was not enough on some
- // configurations (maybe because of IPv6?), causing failures in JDWP
- // host testing; thus it was increased to 256.
- static constexpr size_t kAuxBufSize = 256;
- char auxBuf[kAuxBufSize];
+ std::vector<char> auxBuf(kInitialAuxBufSize);
int error;
- int cc = gethostbyname_r(options->host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
- if (cc != 0) {
+ int cc;
+ while ((cc = gethostbyname_r(
+ options->host.c_str(), &he, auxBuf.data(), auxBuf.size(), &pEntry, &error))
+ == ERANGE) {
+ // The work buffer `auxBuf` is too small; enlarge it.
+ auxBuf.resize(auxBuf.size() * 2);
+ }
+ if (cc != 0 || pEntry == nullptr) {
LOG(WARNING) << "gethostbyname_r('" << options->host << "') failed: " << hstrerror(error);
return false;
}