diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 2dc9f255d7a644f2d6c95310a411b1bc90ba4cf2..24c72c65cede0f674b90b49dcd93a42354d0532e 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -76,6 +76,7 @@ LLLoginInstance::LLLoginInstance() :
 	mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
 	mDispatcher.add("connect",    boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
 	mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
+	mDispatcher.add("indeterminate", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));
 }
 
 LLLoginInstance::~LLLoginInstance()
@@ -204,6 +205,8 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
 		mTransferRate = event["transfer_rate"].asReal();
 	}
 
+	
+
 	// Call the method registered in constructor, if any, for more specific
 	// handling
 	LLEventDispatcher::Callable method(mDispatcher.get(event["change"]));
@@ -295,6 +298,22 @@ void LLLoginInstance::handleDisconnect(const LLSD& event)
     // placeholder
 }
 
+void LLLoginInstance::handleIndeterminate(const LLSD& event)
+{
+	// The indeterminate response means that the server
+	// gave the viewer a new url and params to try.
+	// The login module handles the retry, but it gives us the
+	// server response so that we may show
+	// the user some status.
+	LLSD message = event.get("data").get("message");
+	if(message.isDefined())
+	{
+		LLSD progress_update;
+		progress_update["desc"] = message;
+		LLEventPumps::getInstance()->obtain("LLProgressView").post(progress_update);
+	}
+}
+
 bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
 {
 	if(accepted)
@@ -374,28 +393,6 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
 		mNotifications->add(notification_name, args, payload, 
 			boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
 	}
-
-	/* *NOTE:Mani Experiment with Event API interface.
-	if(!mUpdateAppResponse)
-	{
-		bool make_unique = true;
-		mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique));
-		mUpdateAppResponse->listen("diaupdateDialogCallback", 
-								   boost::bind(&LLLoginInstance::updateDialogCallback,
-								 			   this, _1
-											   )
-								   );
-	}
-
-	LLSD event;
-	event["op"] = "requestAdd";
-	event["name"] = notification_name;
-	event["substitutions"] = args;
-	event["payload"] = payload;
-	event["reply"] = mUpdateAppResponse->getName();
-
-	LLEventPumps::getInstance()->obtain("LLNotifications").post(event);
-	*/
 }
 
 bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response)
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 19d7449bc15bfc7eef3af996c3e7667e014ecbde..c8704eddb497dfb98ae7bebfe2f790d34fb4fa95 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -89,6 +89,7 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	void handleLoginFailure(const LLSD& event);
 	void handleLoginSuccess(const LLSD& event);
 	void handleDisconnect(const LLSD& event);
+	void handleIndeterminate(const LLSD& event);
 
 	bool handleTOSResponse(bool v, const std::string& key);
 
@@ -107,7 +108,6 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance>
 	std::string mSerialNumber;
 	int mLastExecEvent;
 	UpdaterLauncherCallback mUpdaterLauncher;
-	boost::scoped_ptr<LLEventStream> mUpdateAppResponse;
 	LLEventDispatcher mDispatcher;
 };
 
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 5f6b210767d23882de572b2f2e9de0c27dd8ebf3..7a48f890e05bddded44f5a127095b7d3936ac772 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -72,10 +72,12 @@ const S32 ANIMATION_FRAMES = 1; //13;
 LLProgressView::LLProgressView(const LLRect &rect) 
 :	LLPanel(),
 	mPercentDone( 0.f ),
-	mMouseDownInActiveArea( false )
+	mMouseDownInActiveArea( false ),
+	mUpdateEvents("LLProgressView")
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml");
 	reshape(rect.getWidth(), rect.getHeight());
+	mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
 }
 
 BOOL LLProgressView::postBuild()
@@ -260,3 +262,26 @@ void LLProgressView::onClickMessage(void* data)
 		}
 	}
 }
+
+bool LLProgressView::handleUpdate(const LLSD& event_data)
+{
+	LLSD message = event_data.get("message");
+	LLSD desc = event_data.get("desc");
+	LLSD percent = event_data.get("percent");
+
+	if(message.isDefined())
+	{
+		setMessage(message.asString());
+	}
+
+	if(desc.isDefined())
+	{
+		setText(desc.asString());
+	}
+	
+	if(percent.isDefined())
+	{
+		setPercent(percent.asReal());
+	}
+	return false;
+}
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index 865646c85d0b036c35bbe9864704847273851210..6853674d88f2c1a82c84d0e3527b6ac69cae4bed 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -35,6 +35,7 @@
 
 #include "llpanel.h"
 #include "llframetimer.h"
+#include "llevents.h"
 
 class LLImageRaw;
 class LLButton;
@@ -75,7 +76,12 @@ class LLProgressView : public LLPanel
 	LLRect mOutlineRect;
 	bool mMouseDownInActiveArea;
 
+	// The LLEventStream mUpdateEvents depends upon this class being a singleton
+	// to avoid pump name conflicts.
 	static LLProgressView* sInstance;
+	LLEventStream mUpdateEvents; 
+
+	bool handleUpdate(const LLSD& event_data);
 };
 
 #endif // LL_LLPROGRESSVIEW_H
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 73e7d9981509833fd36e4e463149051180c522d1..eb2275bff07d50d1c97f3967c006fd68d21b6dad 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1082,6 +1082,17 @@ bool idle_startup()
 		credentials["passwd"] = gPassword;
 		login->connect(credentials);
 
+		LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
+		return FALSE;
+	}
+
+	if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState())
+	{
+		// If we get here we have gotten past the potential stall
+		// in curl, so take "may appear frozen" out of progress bar. JC
+		auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
+		set_startup_status(progress, auth_desc, auth_message);
+
 		LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
 		return FALSE;
 	}
@@ -1168,16 +1179,6 @@ bool idle_startup()
 				show_connect_box = true;
 			}
 		}
-		else
-		{
-			// Still waiting for response.
-			// *TODO:Mani - Actually check for login progress.
-			// If we get here we have gotten past the potential stall
-			// in curl, so take "may appear frozen" out of progress bar. JC
-			auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
-			set_startup_status(progress, auth_desc, auth_message);
-		}
-
 		return FALSE;
 	}
 
@@ -2703,6 +2704,7 @@ std::string LLStartUp::startupStateToString(EStartupState state)
 		RTNENUM( STATE_LOGIN_WAIT );
 		RTNENUM( STATE_LOGIN_CLEANUP );
 		RTNENUM( STATE_LOGIN_AUTH_INIT );
+		RTNENUM( STATE_LOGIN_CURL_UNSTUCK );
 		RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
 		RTNENUM( STATE_WORLD_INIT );
 		RTNENUM( STATE_MULTIMEDIA_INIT );
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index ab11b42e7427f81c70cbddc08d68c07402e437ad..92fe9521d3eb31b3ca8f2f99e618bc34a5e1c3ad 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -55,6 +55,7 @@ typedef enum {
 	STATE_LOGIN_WAIT,				// Wait for user input at login screen
 	STATE_LOGIN_CLEANUP,			// Get rid of login screen and start login
 	STATE_LOGIN_AUTH_INIT,			// Start login to SL servers
+	STATE_LOGIN_CURL_UNSTUCK,		// Update progress to remove "SL appears frozen" msg.
 	STATE_LOGIN_PROCESS_RESPONSE,	// Check authentication reply
 	STATE_WORLD_INIT,				// Start building the world
 	STATE_MULTIMEDIA_INIT,			// Init the rest of multimedia library
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 018f6916720ef72746e3c0150474e056d9bdc642..364088ab31e9e45929e0f517e8c26279046b5527 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -235,6 +235,8 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
                 break;
             }
 
+			sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
+
             // Here the login service at the current URI is redirecting us
             // to some other URI ("indeterminate" -- why not "redirect"?).
             // The response should contain another uri to try, with its
@@ -276,7 +278,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
     // Here we got through all the rewrittenURIs without succeeding. Tell
     // caller this didn't work out so well. Of course, the only failure data
     // we can reasonably show are from the last of the rewrittenURIs.
-    sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+
+	// *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
+	// llsd with no "responses" node. To make the output from an incomplete login symmetrical 
+	// to success, add a data/message and data/reason fields.
+	LLSD error_response;
+	error_response["reason"] = mAuthResponse["status"];
+	error_response["message"] = mAuthResponse["error"];
+	sendProgressEvent("offline", "fail.login", error_response);
 }
 
 void LLLogin::Impl::disconnect()