diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 110fac0f23..d56bb7aa66 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -34,6 +34,8 @@
#include "llapr.h"
+#include "llrand.h" // FIRE-3877; So we can choose a random port number
+
//virtual
LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
{
@@ -164,8 +166,13 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std
mPluginFile = plugin_filename;
mPluginDir = plugin_dir;
mCPUUsage = 0.0f;
- mDebug = debug;
+ mDebug = debug;
setState(STATE_INITIALIZED);
+
+ // FIRE-3877; Port 0 = choose one for use as default. This was the standard behaviour of LLPluginProcessParent and the reasonable thing to do.
+ mPortToBind = 0;
+ mBindRetries = 0;
+ //
}
bool LLPluginProcessParent::accept()
@@ -274,7 +281,6 @@ void LLPluginProcessParent::idle(void)
case STATE_INITIALIZED:
{
-
apr_status_t status = APR_SUCCESS;
apr_sockaddr_t* addr = NULL;
mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
@@ -286,7 +292,7 @@ void LLPluginProcessParent::idle(void)
&addr,
"127.0.0.1",
APR_INET,
- 0, // port 0 = ephemeral ("find me a port")
+ mPortToBind, // port 0 = ephemeral ("find me a port")
0,
gAPRPoolp);
@@ -324,7 +330,20 @@ void LLPluginProcessParent::idle(void)
LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
killSockets();
- errorState();
+
+ // FIRE-3877; Some drivers, eg bigfoot. Refuse to tell us which port is used when the socket is bound on port 0 (= choose a free port).
+ // If not out of retry attempts, choose a random port between 5500 - 60000 and try again.
+ if( mBindRetries > 10 ) //In theory we could have bad luck and randomly draft already used ports each try. In practice we already deal with a buggy driver anyway. So just fail instead hogging resources in a loop.
+ errorState();
+ else
+ {
+ ++mBindRetries;
+ mPortToBind = ll_rand(55000)+5000; // Ports < 4096 are reserved for root (at least on BSD like systems), do never touch them.
+ setState( STATE_INITIALIZED );
+ idle_again = true; // Just try a new loop to bind the socket
+ }
+ //
+
break;
}
}
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 26c6b0c402..8b9c830f79 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -189,6 +189,11 @@ private:
LLMutex mIncomingQueueMutex;
std::queue mIncomingQueue;
+
+ // FIRE-3877; Bind to a fixed port. Some network drivers (Bigfoot) refuse to tell us to which port a socket is bound if 0 (= choose one) was used.
+ U32 mPortToBind;
+ U32 mBindRetries;
+ //
};
#endif // LL_LLPLUGINPROCESSPARENT_H