diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 95b1d536fe0ed7c33cfee3d6f18334f5c4257373..3a4a8facc217ef7b041d83a614618009bd0901bb 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -337,6 +337,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_CONTEXT_LIBRARY}")
   LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 912270430602f0eddaec965b2732bc6375c5ff62..a629f71d4b94ee74327774b6f011b9a1fdb2aa9e 100755
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -39,7 +39,12 @@
 #include "llerror.h"
 #include "stringize.h"
 
-LLCoros::LLCoros()
+LLCoros::LLCoros():
+    // MAINT-2724: default coroutine stack size too small on Windows.
+    // Previously we used
+    // boost::context::guarded_stack_allocator::default_stacksize();
+    // empirically this is 64KB on Windows and Linux. Try quadrupling.
+    mStackSize(256*1024)
 {
     // Register our cleanup() method for "mainloop" ticks
     LLEventPumps::instance().obtain("mainloop").listen(
@@ -125,6 +130,12 @@ std::string LLCoros::getNameByID(const void* self_id) const
     return "";
 }
 
+void LLCoros::setStackSize(S32 stacksize)
+{
+    LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
+    mStackSize = stacksize;
+}
+
 /*****************************************************************************
 *   MUST BE LAST
 *****************************************************************************/
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 03df406b688d8665a67394432f6c11cfa1f8de1c..01ee11da1ac180419c87b7b6d26d9e0667e0399c 100755
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -125,7 +125,7 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
     template <typename CALLABLE>
     std::string launch(const std::string& prefix, const CALLABLE& callable)
     {
-        return launchImpl(prefix, new coro(callable));
+        return launchImpl(prefix, new coro(callable, mStackSize));
     }
 
     /**
@@ -152,6 +152,9 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
     /// getName() by self.get_id()
     std::string getNameByID(const void* self_id) const;
 
+    /// for delayed initialization
+    void setStackSize(S32 stacksize);
+
 private:
     friend class LLSingleton<LLCoros>;
     LLCoros();
@@ -159,6 +162,7 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
     std::string generateDistinctName(const std::string& prefix) const;
     bool cleanup(const LLSD&);
 
+    S32 mStackSize;
     typedef boost::ptr_map<std::string, coro> CoroMap;
     CoroMap mCoros;
 };
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index 8d12529613e0fe0a525a69cbca77845ffb810f7d..5ebde1a31df880b7e3b9de4cc911a982c38cf5d0 100755
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -78,6 +78,7 @@
 
 #include "../test/lltut.h"
 #include "llsd.h"
+#include "llsdutil.h"
 #include "llevents.h"
 #include "tests/wrapllerrs.h"
 #include "stringize.h"
@@ -108,7 +109,7 @@ match_substring(BidirectionalIterator begin,
 		BidirectionalIterator end, 
 		std::string xmatch,
 		BOOST_DEDUCED_TYPENAME coroutine<BidirectionalIterator(void)>::self& self) { 
-  BidirectionalIterator begin_ = begin;
+//BidirectionalIterator begin_ = begin;
   for(; begin != end; ++begin) 
     if(match(begin, end, xmatch)) {
       self.yield(begin);
@@ -213,7 +214,7 @@ namespace tut
             BEGIN
             {
                 result = postAndWait(self,
-                                     LLSD().insert("value", 17), // request event
+                                     LLSDMap("value", 17),       // request event
                                      immediateAPI.getPump(),     // requestPump
                                      "reply1",                   // replyPump
                                      "reply");                   // request["reply"] = name
@@ -226,7 +227,7 @@ namespace tut
             BEGIN
             {
                 LLEventWithID pair = ::postAndWait2(self,
-                                                    LLSD().insert("value", 18),
+                                                    LLSDMap("value", 18),
                                                     immediateAPI.getPump(),
                                                     "reply2",
                                                     "error2",
@@ -244,7 +245,7 @@ namespace tut
             BEGIN
             {
                 LLEventWithID pair = ::postAndWait2(self,
-                                                    LLSD().insert("value", 18).insert("fail", LLSD()),
+                                                    LLSDMap("value", 18)("fail", LLSD()),
                                                     immediateAPI.getPump(),
                                                     "reply2",
                                                     "error2",
@@ -273,7 +274,7 @@ namespace tut
             BEGIN
             {
                 LLCoroEventPump waiter;
-                result = waiter.postAndWait(self, LLSD().insert("value", 17),
+                result = waiter.postAndWait(self, LLSDMap("value", 17),
                                             immediateAPI.getPump(), "reply");
             }
             END
@@ -365,7 +366,7 @@ namespace tut
             BEGIN
             {
                 LLCoroEventPumps waiter;
-                LLEventWithID pair(waiter.postAndWait(self, LLSD().insert("value", 23),
+                LLEventWithID pair(waiter.postAndWait(self, LLSDMap("value", 23),
                                                       immediateAPI.getPump(), "reply", "error"));
                 result = pair.first;
                 which  = pair.second;
@@ -379,7 +380,7 @@ namespace tut
             {
                 LLCoroEventPumps waiter;
                 LLEventWithID pair(
-                    waiter.postAndWait(self, LLSD().insert("value", 23).insert("fail", LLSD()),
+                    waiter.postAndWait(self, LLSDMap("value", 23)("fail", LLSD()),
                                        immediateAPI.getPump(), "reply", "error"));
                 result = pair.first;
                 which  = pair.second;
@@ -392,7 +393,7 @@ namespace tut
             BEGIN
             {
                 LLCoroEventPumps waiter;
-                result = waiter.postAndWaitWithException(self, LLSD().insert("value", 8),
+                result = waiter.postAndWaitWithException(self, LLSDMap("value", 8),
                                                          immediateAPI.getPump(), "reply", "error");
             }
             END
@@ -406,7 +407,7 @@ namespace tut
                 try
                 {
                     result = waiter.postAndWaitWithException(self,
-                        LLSD().insert("value", 9).insert("fail", LLSD()),
+                        LLSDMap("value", 9)("fail", LLSD()),
                         immediateAPI.getPump(), "reply", "error");
                     debug("no exception");
                 }
@@ -424,7 +425,7 @@ namespace tut
             BEGIN
             {
                 LLCoroEventPumps waiter;
-                result = waiter.postAndWaitWithLog(self, LLSD().insert("value", 30),
+                result = waiter.postAndWaitWithLog(self, LLSDMap("value", 30),
                                                    immediateAPI.getPump(), "reply", "error");
             }
             END
@@ -439,7 +440,7 @@ namespace tut
                 try
                 {
                     result = waiter.postAndWaitWithLog(self,
-                        LLSD().insert("value", 31).insert("fail", LLSD()),
+                        LLSDMap("value", 31)("fail", LLSD()),
                         immediateAPI.getPump(), "reply", "error");
                     debug("no exception");
                 }
@@ -796,4 +797,18 @@ namespace tut
         ensure("no result", result.isUndefined());
         ensure_contains("got error", threw, "32");
     }
+}
+
+/*==========================================================================*|
+#include <boost/context/guarded_stack_allocator.hpp>
+
+namespace tut
+{
+    template<> template<>
+    void object::test<23>()
+    {
+        set_test_name("stacksize");
+        std::cout << "default_stacksize: " << boost::context::guarded_stack_allocator::default_stacksize() << '\n';
+    }
 } // namespace tut
+|*==========================================================================*/
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index b3538bf069eb907c1a501f313561732e5cff1904..f356cff9d89fd3cb1b610e5656189116a79b5f23 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1905,6 +1905,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>CoroutineStackSize</key>
+    <map>
+      <key>Comment</key>
+      <string>Size (in bytes) for each coroutine stack</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>262144</integer>
+    </map>
     <key>CreateToolCopyCenters</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 45a990f65f1bc1def45f3eb0c3145b710d9f1a1b..fdc2cdb78db80943f97d916cc37af8e94fcdee66 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -117,6 +117,7 @@
 
 #include "llleap.h"
 #include "stringize.h"
+#include "llcoros.h"
 
 // Third party library includes
 #include <boost/bind.hpp>
@@ -755,6 +756,7 @@ bool LLAppViewer::init()
 
 	//set the max heap size.
 	initMaxHeapSize() ;
+	LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
 
 	LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")*1024*1024) ;
 
@@ -2810,6 +2812,16 @@ bool LLAppViewer::initConfiguration()
 
 	loadColorSettings();
 
+	// Let anyone else who cares know that we've populated our settings
+	// variables.
+	for (LLControlGroup::key_iter ki(LLControlGroup::beginKeys()), kend(LLControlGroup::endKeys());
+		 ki != kend; ++ki)
+	{
+		// For each named instance of LLControlGroup, send an event saying
+		// we've initialized an LLControlGroup instance by that name.
+		LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", *ki));
+	}
+
 	return true; // Config was successful.
 }