From 5fe0820e138d14bbe42911f65d6ed4e43196ebd7 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 12 Dec 2012 16:14:32 +0100 Subject: [PATCH] Login crash bug fix. XMLRPCResponder constructor was missing. This fixes the following crash signature: VIEWER : 2012-12-12T14:25:13Z INFO("AppInit"): setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING VIEWER : 2012-12-12T14:25:14Z INFO("AppInit"): transferRate: Buffer size: 1308 B VIEWER : 2012-12-12T14:25:14Z INFO("AppInit"): transferRate: Transfer rate: 11 kb/s Program received signal SIGSEGV, Segmentation fault. 0x00007ffff33df7f5 in XMLRPC_RequestGetData () from /usr/lib/x86_64-linux-gnu/libxmlrpc-epi.so.0 (gdb) bt Reason was that if the server replied with some error code then mResponse was undefined. I also added code to retry three times in that case; the http status code that I get was 503, which really mean "Service *temporarily* unavailable", so a retry is in order. --- indra/newview/llstartup.cpp | 14 +++++++------- indra/newview/lluserauth.cpp | 11 ++++++++++- indra/newview/lluserauth.h | 1 + indra/newview/llxmlrpcresponder.h | 2 ++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cb82d8722..6d1e2d92c 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1432,7 +1432,6 @@ bool idle_startup() LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL; return FALSE; } - Debug(if (gCurlIo) dc::curlio.off()); // Login succeeded: restore dc::curlio to original state. LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE ); progress += 0.01f; set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message); @@ -1469,6 +1468,7 @@ bool idle_startup() { // Yay, login! successful_login = true; + Debug(if (gCurlIo) dc::curlio.off()); // Login succeeded: restore dc::curlio to original state. } else { @@ -1548,13 +1548,12 @@ bool idle_startup() } } break; - case LLUserAuth::E_COULDNT_RESOLVE_HOST: - case LLUserAuth::E_SSL_PEER_CERTIFICATE: - case LLUserAuth::E_UNHANDLED_ERROR: - case LLUserAuth::E_SSL_CACERT: - case LLUserAuth::E_SSL_CONNECT_ERROR: default: - if (LLViewerLogin::getInstance()->tryNextURI()) + { + static int http_failures = 0; + http_failures = (error == LLUserAuth::E_HTTP_SERVER_ERROR) ? http_failures + 1 : 0; + if ((error == LLUserAuth::E_HTTP_SERVER_ERROR && http_failures <= 3) || + LLViewerLogin::getInstance()->tryNextURI()) { static int login_attempt_number = 0; std::ostringstream s; @@ -1569,6 +1568,7 @@ bool idle_startup() emsg << "Unable to connect to " << gHippoGridManager->getCurrentGrid()->getGridName() << ".\n"; emsg << LLUserAuth::getInstance()->errorMessage(); } + } break; } diff --git a/indra/newview/lluserauth.cpp b/indra/newview/lluserauth.cpp index a692f9575..a0791989e 100644 --- a/indra/newview/lluserauth.cpp +++ b/indra/newview/lluserauth.cpp @@ -323,7 +323,16 @@ LLUserAuth::UserAuthcode LLUserAuth::parseResponse() // will all be string => string pairs. UserAuthcode rv = E_UNHANDLED_ERROR; XMLRPC_REQUEST response = mResponder->response(); - if(!response) return rv; + if(!response) + { + U32 status = mResponder->http_status(); + // Is it an HTTP error? + if (!(200 <= status && status < 400)) + { + rv = E_HTTP_SERVER_ERROR; + } + return rv; + } // clear out any old parsing mResponses.clear(); diff --git a/indra/newview/lluserauth.h b/indra/newview/lluserauth.h index 847b1e8b5..1bc76cb84 100644 --- a/indra/newview/lluserauth.h +++ b/indra/newview/lluserauth.h @@ -88,6 +88,7 @@ public: E_SSL_PEER_CERTIFICATE, E_SSL_CACERT, E_SSL_CONNECT_ERROR, + E_HTTP_SERVER_ERROR, E_UNHANDLED_ERROR, E_LAST // never use! } UserAuthcode; diff --git a/indra/newview/llxmlrpcresponder.h b/indra/newview/llxmlrpcresponder.h index df01692ae..dbaa45260 100644 --- a/indra/newview/llxmlrpcresponder.h +++ b/indra/newview/llxmlrpcresponder.h @@ -99,6 +99,8 @@ private: XMLRPC_REQUEST mResponse; public: + XMLRPCResponder(void) : mBufferSize(0), mReceivedHTTPHeader(false), mResponse(NULL) { } + // Accessors. F64 transferRate(void) const; bool is_downloading(void) const { return mReceivedHTTPHeader; }