Fix deadlock
This commit is contained in:
@@ -62,6 +62,111 @@ namespace ANSCENTER
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
// SummarizeChilkatError: turn Chilkat's verbose multi-line lastErrorText()
|
||||
// into a single diagnostic line suitable for _logger.LogError().
|
||||
//
|
||||
// Chilkat's log looks like:
|
||||
// ChilkatLog: Connect: DllDate: ... ChilkatVersion: ... UnlockStatus: ...
|
||||
// restConnect: domain_or_ip: s3.us-east-1.amazonaws.com
|
||||
// socket2Connect: connect2: connectImplicitSsl: connectSocket_v2:
|
||||
// connect_domain: ckDnsResolveDomainIPv4_n: ...
|
||||
// clientHandshake2: readHandshakeMessages:
|
||||
// Failed to read beginning of SSL/TLS record.
|
||||
// readTlsRecord: Socket operation timeout.
|
||||
// See https://cknotes.com/...
|
||||
// ConnectFailReason: 103
|
||||
// Failed.
|
||||
//
|
||||
// Diagnostics we care about:
|
||||
// • the deepest concrete failure reason (the non-label leaf line)
|
||||
// • ConnectFailReason: <N> if present
|
||||
// • the target (domain_or_ip / ip_or_domain + port)
|
||||
// Rest (DllDate, ChilkatVersion, Architecture, VerboseLogging, ...) is noise.
|
||||
//
|
||||
// Returns e.g.:
|
||||
// "Connect failed [reason=103] s3.us-east-1.amazonaws.com:443 — Socket operation timeout (TLS handshake). See https://cknotes.com/failed-to-read-beginning-of-ssl-tls-record-..."
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
static std::string SummarizeChilkatError(const char* raw) {
|
||||
if (!raw || !*raw) return "(empty Chilkat log)";
|
||||
std::string s(raw);
|
||||
// Split into trimmed lines.
|
||||
std::vector<std::string> lines;
|
||||
{
|
||||
std::istringstream iss(s);
|
||||
std::string ln;
|
||||
while (std::getline(iss, ln)) {
|
||||
// Trim leading whitespace (Chilkat indents by level).
|
||||
size_t a = ln.find_first_not_of(" \t\r\n");
|
||||
if (a == std::string::npos) continue;
|
||||
size_t b = ln.find_last_not_of(" \t\r\n");
|
||||
lines.push_back(ln.substr(a, b - a + 1));
|
||||
}
|
||||
}
|
||||
if (lines.empty()) return "(empty Chilkat log)";
|
||||
|
||||
// Lines that are pure labels ("foo:" or "--foo") are scaffolding.
|
||||
auto isLabelLine = [](const std::string& ln) {
|
||||
if (ln.empty()) return true;
|
||||
if (ln.rfind("--", 0) == 0) return true; // "--foo" close-marker
|
||||
// "label: value" — keep only if value is non-empty and line doesn't
|
||||
// look like pure call-stack breadcrumb (trailing ':').
|
||||
if (!ln.empty() && ln.back() == ':') return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
// Fields we want to extract.
|
||||
std::string target, failReason, tlsHint, leafError, seeUrl;
|
||||
|
||||
for (auto& ln : lines) {
|
||||
if (ln.rfind("domain_or_ip:", 0) == 0 || ln.rfind("ip_or_domain:", 0) == 0) {
|
||||
auto p = ln.find(':');
|
||||
if (p != std::string::npos) target = ln.substr(p + 1);
|
||||
} else if (ln.rfind("ConnectFailReason:", 0) == 0) {
|
||||
auto p = ln.find(':');
|
||||
if (p != std::string::npos) failReason = ln.substr(p + 1);
|
||||
} else if (ln.rfind("port:", 0) == 0) {
|
||||
auto p = ln.find(':');
|
||||
if (p != std::string::npos) {
|
||||
// Append port to target if we have one.
|
||||
std::string port = ln.substr(p + 1);
|
||||
// Trim leading space.
|
||||
size_t a = port.find_first_not_of(" \t");
|
||||
if (a != std::string::npos) port = port.substr(a);
|
||||
if (!target.empty()) target += ":" + port;
|
||||
}
|
||||
} else if (ln.rfind("See http", 0) == 0 || ln.rfind("See https", 0) == 0) {
|
||||
seeUrl = ln.substr(4); // drop "See "
|
||||
} else if (ln.rfind("Failed to read beginning of SSL/TLS record", 0) == 0) {
|
||||
tlsHint = "TLS handshake — server sent nothing (firewall/AV TLS inspection, proxy, or packet loss)";
|
||||
} else if (!isLabelLine(ln)) {
|
||||
// Candidate concrete message. Keep the LATEST one that's not a
|
||||
// stack label; Chilkat's deepest concrete error is usually the
|
||||
// most specific explanation.
|
||||
leafError = ln;
|
||||
}
|
||||
}
|
||||
|
||||
// Trim leading space on captured fields.
|
||||
auto trim = [](std::string& v) {
|
||||
size_t a = v.find_first_not_of(" \t");
|
||||
if (a == std::string::npos) { v.clear(); return; }
|
||||
size_t b = v.find_last_not_of(" \t");
|
||||
v = v.substr(a, b - a + 1);
|
||||
};
|
||||
trim(target); trim(failReason); trim(leafError); trim(seeUrl);
|
||||
|
||||
// Compose.
|
||||
std::ostringstream out;
|
||||
out << "Chilkat Connect failed";
|
||||
if (!failReason.empty()) out << " [reason=" << failReason << "]";
|
||||
if (!target.empty()) out << " " << target;
|
||||
if (!leafError.empty()) out << " — " << leafError;
|
||||
if (!tlsHint.empty()) out << " (" << tlsHint << ")";
|
||||
if (!seeUrl.empty()) out << " (" << seeUrl << ")";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
// Private helper function to extract file name from a path
|
||||
// Helper function to extract filename from path
|
||||
std::string ANSAWSS3::ExtractFileName(const std::string& filePath) {
|
||||
@@ -249,7 +354,9 @@ namespace ANSCENTER
|
||||
|
||||
// Connect
|
||||
if (!conn->rest.Connect(_fullAWSURL.c_str(), _port, _bTls, _bAutoReconnect)) {
|
||||
_logger.LogError("ANSAWSS3::CreateConnection", conn->rest.lastErrorText(), __FILE__, __LINE__);
|
||||
const std::string summary = SummarizeChilkatError(conn->rest.lastErrorText());
|
||||
_logger.LogError("ANSAWSS3::CreateConnection", summary, __FILE__, __LINE__);
|
||||
ANS_DBG("AWSS3", "Connect failed: %s", summary.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -261,7 +368,9 @@ namespace ANSCENTER
|
||||
conn->socket.put_HttpProxyPassword(_proxyPassword.c_str());
|
||||
conn->socket.put_HttpProxyForHttp(_bProxy);
|
||||
if (!conn->rest.UseConnection(conn->socket, true)) {
|
||||
_logger.LogError("ANSAWSS3::CreateConnection - Proxy error", conn->rest.lastErrorText(), __FILE__, __LINE__);
|
||||
const std::string summary = SummarizeChilkatError(conn->rest.lastErrorText());
|
||||
_logger.LogError("ANSAWSS3::CreateConnection - Proxy error", summary, __FILE__, __LINE__);
|
||||
ANS_DBG("AWSS3", "Proxy error: %s", summary.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -275,7 +384,9 @@ namespace ANSCENTER
|
||||
if (!_bucketRegion.empty()) conn->authAws.put_Region(_bucketRegion.c_str());
|
||||
}
|
||||
if (!conn->rest.SetAuthAws(conn->authAws)) {
|
||||
_logger.LogError("ANSAWSS3::CreateConnection - Auth error", conn->rest.lastErrorText(), __FILE__, __LINE__);
|
||||
const std::string summary = SummarizeChilkatError(conn->rest.lastErrorText());
|
||||
_logger.LogError("ANSAWSS3::CreateConnection - Auth error", summary, __FILE__, __LINE__);
|
||||
ANS_DBG("AWSS3", "Auth error: %s", summary.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user