aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llplugin/llpluginprocessparent.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xlinden/indra/llplugin/llpluginprocessparent.cpp123
1 files changed, 56 insertions, 67 deletions
diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp
index 8fd18ef..5a66279 100755
--- a/linden/indra/llplugin/llpluginprocessparent.cpp
+++ b/linden/indra/llplugin/llpluginprocessparent.cpp
@@ -49,6 +49,7 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
49 49
50bool LLPluginProcessParent::sUseReadThread = false; 50bool LLPluginProcessParent::sUseReadThread = false;
51apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; 51apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
52AIAPRPool LLPluginProcessParent::sPollSetPool;
52bool LLPluginProcessParent::sPollsetNeedsRebuild = false; 53bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
53LLMutex *LLPluginProcessParent::sInstancesMutex; 54LLMutex *LLPluginProcessParent::sInstancesMutex;
54std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances; 55std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
@@ -59,7 +60,7 @@ class LLPluginProcessParentPollThread: public LLThread
59{ 60{
60public: 61public:
61 LLPluginProcessParentPollThread() : 62 LLPluginProcessParentPollThread() :
62 LLThread("LLPluginProcessParentPollThread", gAPRPoolp) 63 LLThread("LLPluginProcessParentPollThread")
63 { 64 {
64 } 65 }
65protected: 66protected:
@@ -84,12 +85,11 @@ protected:
84 85
85}; 86};
86 87
87LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): 88LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
88 mIncomingQueueMutex(gAPRPoolp)
89{ 89{
90 if(!sInstancesMutex) 90 if(!sInstancesMutex)
91 { 91 {
92 sInstancesMutex = new LLMutex(gAPRPoolp); 92 sInstancesMutex = new LLMutex;
93 } 93 }
94 94
95 mOwner = owner; 95 mOwner = owner;
@@ -102,6 +102,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
102 mBlocked = false; 102 mBlocked = false;
103 mPolledInput = false; 103 mPolledInput = false;
104 mPollFD.client_data = NULL; 104 mPollFD.client_data = NULL;
105 mPollFDPool.create();
105 106
106 mPluginLaunchTimeout = 60.0f; 107 mPluginLaunchTimeout = 60.0f;
107 mPluginLockupTimeout = 15.0f; 108 mPluginLockupTimeout = 15.0f;
@@ -119,7 +120,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
119 120
120LLPluginProcessParent::~LLPluginProcessParent() 121LLPluginProcessParent::~LLPluginProcessParent()
121{ 122{
122 LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; 123 LL_DEBUGS("PluginParent") << "destructor" << LL_ENDL;
123 124
124 // Remove from the global list before beginning destruction. 125 // Remove from the global list before beginning destruction.
125 { 126 {
@@ -177,44 +178,28 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std
177bool LLPluginProcessParent::accept() 178bool LLPluginProcessParent::accept()
178{ 179{
179 bool result = false; 180 bool result = false;
180
181 apr_status_t status = APR_EGENERAL; 181 apr_status_t status = APR_EGENERAL;
182 apr_socket_t *new_socket = NULL;
183
184 status = apr_socket_accept(
185 &new_socket,
186 mListenSocket->getSocket(),
187 gAPRPoolp);
188 182
183 mSocket = LLSocket::create(status, mListenSocket);
189 184
190 if(status == APR_SUCCESS) 185 if(status == APR_SUCCESS)
191 { 186 {
192// llinfos << "SUCCESS" << llendl; 187// llinfos << "SUCCESS" << llendl;
193 // Success. Create a message pipe on the new socket 188 // Success. Create a message pipe on the new socket
194
195 // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor!
196 apr_pool_t* new_pool = NULL;
197 status = apr_pool_create(&new_pool, gAPRPoolp);
198
199 mSocket = LLSocket::create(new_socket, new_pool);
200 new LLPluginMessagePipe(this, mSocket); 189 new LLPluginMessagePipe(this, mSocket);
201 190
202 result = true; 191 result = true;
203 } 192 }
204 else if(APR_STATUS_IS_EAGAIN(status))
205 {
206// llinfos << "EAGAIN" << llendl;
207
208 // No incoming connections. This is not an error.
209 status = APR_SUCCESS;
210 }
211 else 193 else
212 { 194 {
213// llinfos << "Error:" << llendl; 195 mSocket.reset();
214 ll_apr_warn_status(status); 196 // EAGAIN means "No incoming connections". This is not an error.
215 197 if (!APR_STATUS_IS_EAGAIN(status))
216 // Some other error. 198 {
217 errorState(); 199 // Some other error.
200 ll_apr_warn_status(status);
201 errorState();
202 }
218 } 203 }
219 204
220 return result; 205 return result;
@@ -264,10 +249,10 @@ void LLPluginProcessParent::idle(void)
264 else if(mSocketError != APR_SUCCESS) 249 else if(mSocketError != APR_SUCCESS)
265 { 250 {
266 // The socket is in an error state -- the plugin is gone. 251 // The socket is in an error state -- the plugin is gone.
267 LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; 252 LL_WARNS("PluginParent") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
268 errorState(); 253 errorState();
269 } 254 }
270 } 255 }
271 256
272 // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). 257 // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
273 // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. 258 // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
@@ -283,7 +268,7 @@ void LLPluginProcessParent::idle(void)
283 268
284 apr_status_t status = APR_SUCCESS; 269 apr_status_t status = APR_SUCCESS;
285 apr_sockaddr_t* addr = NULL; 270 apr_sockaddr_t* addr = NULL;
286 mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); 271 mListenSocket = LLSocket::create(LLSocket::STREAM_TCP);
287 mBoundPort = 0; 272 mBoundPort = 0;
288 273
289 // This code is based on parts of LLSocket::create() in lliosocket.cpp. 274 // This code is based on parts of LLSocket::create() in lliosocket.cpp.
@@ -294,7 +279,7 @@ void LLPluginProcessParent::idle(void)
294 APR_INET, 279 APR_INET,
295 0, // port 0 = ephemeral ("find me a port") 280 0, // port 0 = ephemeral ("find me a port")
296 0, 281 0,
297 gAPRPoolp); 282 AIAPRRootPool::get()());
298 283
299 if(ll_apr_warn_status(status)) 284 if(ll_apr_warn_status(status))
300 { 285 {
@@ -327,15 +312,15 @@ void LLPluginProcessParent::idle(void)
327 312
328 if(mBoundPort == 0) 313 if(mBoundPort == 0)
329 { 314 {
330 LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL; 315 LL_WARNS("PluginParent") << "Bound port number unknown, bailing out." << LL_ENDL;
331 316
332 killSockets(); 317 killSockets();
333 errorState(); 318 errorState();
334 break; 319 break;
335 } 320 }
336 } 321 }
337 322
338 LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL; 323 LL_DEBUGS("PluginParent") << "Bound tcp socket to port: " << addr->port << LL_ENDL;
339 324
340 // Make the listen socket non-blocking 325 // Make the listen socket non-blocking
341 status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1); 326 status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1);
@@ -458,8 +443,8 @@ void LLPluginProcessParent::idle(void)
458 break; 443 break;
459 444
460 case STATE_HELLO: 445 case STATE_HELLO:
461 LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL; 446 LL_DEBUGS("PluginParent") << "received hello message" << LL_ENDL;
462 447
463 // Send the message to load the plugin 448 // Send the message to load the plugin
464 { 449 {
465 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); 450 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin");
@@ -492,7 +477,7 @@ void LLPluginProcessParent::idle(void)
492 } 477 }
493 else if(pluginLockedUp()) 478 else if(pluginLockedUp())
494 { 479 {
495 LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL; 480 LL_WARNS("PluginParent") << "timeout in exiting state, bailing out" << LL_ENDL;
496 errorState(); 481 errorState();
497 } 482 }
498 break; 483 break;
@@ -589,11 +574,11 @@ void LLPluginProcessParent::sendMessage(const LLPluginMessage &message)
589 // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. 574 // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked.
590 mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); 575 mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
591 } 576 }
592 577
593 std::string buffer = message.generate(); 578 std::string buffer = message.generate();
594 LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; 579 LL_DEBUGS("PluginParent") << "Sending: " << buffer << LL_ENDL;
595 writeMessageRaw(buffer); 580 writeMessageRaw(buffer);
596 581
597 // Try to send message immediately. 582 // Try to send message immediately.
598 if(mMessagePipe) 583 if(mMessagePipe)
599 { 584 {
@@ -617,7 +602,8 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe)
617 if(message_pipe != NULL) 602 if(message_pipe != NULL)
618 { 603 {
619 // Set up the apr_pollfd_t 604 // Set up the apr_pollfd_t
620 mPollFD.p = gAPRPoolp; 605
606 mPollFD.p = mPollFDPool();
621 mPollFD.desc_type = APR_POLL_SOCKET; 607 mPollFD.desc_type = APR_POLL_SOCKET;
622 mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; 608 mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP;
623 mPollFD.rtnevents = 0; 609 mPollFD.rtnevents = 0;
@@ -664,6 +650,7 @@ void LLPluginProcessParent::updatePollset()
664 // delete the existing pollset. 650 // delete the existing pollset.
665 apr_pollset_destroy(sPollSet); 651 apr_pollset_destroy(sPollSet);
666 sPollSet = NULL; 652 sPollSet = NULL;
653 sPollSetPool.destroy();
667 } 654 }
668 655
669 std::list<LLPluginProcessParent*>::iterator iter; 656 std::list<LLPluginProcessParent*>::iterator iter;
@@ -686,12 +673,14 @@ void LLPluginProcessParent::updatePollset()
686 { 673 {
687#ifdef APR_POLLSET_NOCOPY 674#ifdef APR_POLLSET_NOCOPY
688 // The pollset doesn't exist yet. Create it now. 675 // The pollset doesn't exist yet. Create it now.
689 apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); 676 sPollSetPool.create();
677 apr_status_t status = apr_pollset_create(&sPollSet, count, sPollSetPool(), APR_POLLSET_NOCOPY);
690 if(status != APR_SUCCESS) 678 if(status != APR_SUCCESS)
691 { 679 {
692#endif // APR_POLLSET_NOCOPY 680#endif // APR_POLLSET_NOCOPY
693 LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; 681 LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL;
694 sPollSet = NULL; 682 sPollSet = NULL;
683 sPollSetPool.destroy();
695#ifdef APR_POLLSET_NOCOPY 684#ifdef APR_POLLSET_NOCOPY
696 } 685 }
697 else 686 else
@@ -851,8 +840,8 @@ void LLPluginProcessParent::servicePoll()
851 840
852void LLPluginProcessParent::receiveMessageRaw(const std::string &message) 841void LLPluginProcessParent::receiveMessageRaw(const std::string &message)
853{ 842{
854 LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; 843 LL_DEBUGS("PluginParent") << "Received: " << message << LL_ENDL;
855 844
856 LLPluginMessage parsed; 845 LLPluginMessage parsed;
857 if(parsed.parse(message) != -1) 846 if(parsed.parse(message) != -1)
858 { 847 {
@@ -918,19 +907,19 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
918 } 907 }
919 else 908 else
920 { 909 {
921 LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL; 910 LL_WARNS("PluginParent") << "received hello message in wrong state -- bailing out" << LL_ENDL;
922 errorState(); 911 errorState();
923 } 912 }
924 913
925 } 914 }
926 else if(message_name == "load_plugin_response") 915 else if(message_name == "load_plugin_response")
927 { 916 {
928 if(mState == STATE_LOADING) 917 if(mState == STATE_LOADING)
929 { 918 {
930 // Plugin has been loaded. 919 // Plugin has been loaded.
931 920
932 mPluginVersionString = message.getValue("plugin_version"); 921 mPluginVersionString = message.getValue("plugin_version");
933 LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL; 922 LL_INFOS("PluginParent") << "plugin version string: " << mPluginVersionString << LL_ENDL;
934 923
935 // Check which message classes/versions the plugin supports. 924 // Check which message classes/versions the plugin supports.
936 // TODO: check against current versions 925 // TODO: check against current versions
@@ -939,9 +928,9 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
939 LLSD::map_iterator iter; 928 LLSD::map_iterator iter;
940 for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++) 929 for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++)
941 { 930 {
942 LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL; 931 LL_INFOS("PluginParent") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
943 } 932 }
944 933
945 // Send initial sleep time 934 // Send initial sleep time
946 setSleepTime(mSleepTime, true); 935 setSleepTime(mSleepTime, true);
947 936
@@ -949,7 +938,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
949 } 938 }
950 else 939 else
951 { 940 {
952 LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL; 941 LL_WARNS("PluginParent") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
953 errorState(); 942 errorState();
954 } 943 }
955 } 944 }
@@ -960,8 +949,8 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
960 949
961 mCPUUsage = message.getValueReal("cpu_usage"); 950 mCPUUsage = message.getValueReal("cpu_usage");
962 951
963 LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL; 952 LL_DEBUGS("PluginSpam") << "cpu usage reported as " << mCPUUsage << LL_ENDL;
964 953
965 } 954 }
966 else if(message_name == "shm_add_response") 955 else if(message_name == "shm_add_response")
967 { 956 {
@@ -983,7 +972,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
983 } 972 }
984 else 973 else
985 { 974 {
986 LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL; 975 LL_WARNS("PluginParent") << "Unknown internal message from child: " << message_name << LL_ENDL;
987 } 976 }
988 } 977 }
989 else 978 else
@@ -1015,7 +1004,7 @@ std::string LLPluginProcessParent::addSharedMemory(size_t size)
1015 } 1004 }
1016 else 1005 else
1017 { 1006 {
1018 LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; 1007 LL_WARNS("PluginParent") << "Couldn't create a shared memory segment!" << LL_ENDL;
1019 1008
1020 // Don't leak 1009 // Don't leak
1021 delete region; 1010 delete region;
@@ -1037,7 +1026,7 @@ void LLPluginProcessParent::removeSharedMemory(const std::string &name)
1037 } 1026 }
1038 else 1027 else
1039 { 1028 {
1040 LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL; 1029 LL_WARNS("PluginParent") << "Request to remove an unknown shared memory segment." << LL_ENDL;
1041 } 1030 }
1042} 1031}
1043size_t LLPluginProcessParent::getSharedMemorySize(const std::string &name) 1032size_t LLPluginProcessParent::getSharedMemorySize(const std::string &name)
@@ -1084,25 +1073,25 @@ std::string LLPluginProcessParent::getPluginVersion(void)
1084 1073
1085void LLPluginProcessParent::setState(EState state) 1074void LLPluginProcessParent::setState(EState state)
1086{ 1075{
1087 LL_DEBUGS("Plugin") << "setting state to " << stateToString(state) << LL_ENDL; 1076 LL_DEBUGS("PluginParent") << "setting state to " << stateToString(state) << LL_ENDL;
1088 mState = state; 1077 mState = state;
1089}; 1078};
1090 1079
1091bool LLPluginProcessParent::pluginLockedUpOrQuit() 1080bool LLPluginProcessParent::pluginLockedUpOrQuit()
1092{ 1081{
1093 bool result = false; 1082 bool result = false;
1094 1083
1095 if(!mProcess.isRunning()) 1084 if(!mProcess.isRunning())
1096 { 1085 {
1097 LL_WARNS("Plugin") << "child exited" << LL_ENDL; 1086 LL_WARNS("PluginParent") << "child exited" << LL_ENDL;
1098 result = true; 1087 result = true;
1099 } 1088 }
1100 else if(pluginLockedUp()) 1089 else if(pluginLockedUp())
1101 { 1090 {
1102 LL_WARNS("Plugin") << "timeout" << LL_ENDL; 1091 LL_WARNS("PluginParent") << "timeout" << LL_ENDL;
1103 result = true; 1092 result = true;
1104 } 1093 }
1105 1094
1106 return result; 1095 return result;
1107} 1096}
1108 1097