Add support for flushing messages from plugin to viewer.
Actually flush messages before terminating a plugin (upon the shutdown message) and flush messages in the file- and dirpicker before opening the blocking dialog. Flush debug messages too (deeper into the code, just prior to the actual blocking call). Also, fix the context folder map to be a thread-safe singleton and *attempt* to add support for default folders to windows and Mac. The latter might even not compile yet and definitely have to be tested (and fixed): Opening a DirPicker in preferences --> Network and Set the directory location of the cache. It should open a Dialog window where you are already in the folder that is the current cache directory setting (you can click Cancel after verifying that this worked). And, start to upload an image, select a file is some directory (other than what it starts in). You can omit the actual upload by clicking cancel in the preview. Then upload again and now it should start in the same folder as that you were just in. Possibly you need to first open a file picker elsewhere with a different context though, or windows might choose to open in the last folder anyway while the code doesn't really work. Uploading a sound before the second texture upload should do the trick.
This commit is contained in:
@@ -89,6 +89,16 @@ bool LLPluginMessagePipeOwner::writeMessageRaw(const std::string &message)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LLPluginMessagePipeOwner::flushMessages(void)
|
||||
{
|
||||
bool result = true;
|
||||
if (mMessagePipe != NULL)
|
||||
{
|
||||
result = mMessagePipe->flushMessages();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLPluginMessagePipeOwner::killMessagePipe(void)
|
||||
{
|
||||
if(mMessagePipe != NULL)
|
||||
@@ -163,26 +173,32 @@ bool LLPluginMessagePipe::pump(F64 timeout)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LLPluginMessagePipe::pumpOutput()
|
||||
static apr_interval_time_t const flush_max_block_time = 10000000; // Even when flushing, give up after 10 seconds.
|
||||
static apr_interval_time_t const flush_min_timeout = 1000; // When flushing, initially timeout after 1 ms.
|
||||
static apr_interval_time_t const flush_max_timeout = 50000; // Never wait longer than 50 ms.
|
||||
|
||||
// DO NOT SET 'flush' TO TRUE WHEN CALLED ON THE VIEWER SIDE!
|
||||
// flush is only intended for plugin-side.
|
||||
bool LLPluginMessagePipe::pumpOutput(bool flush)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if(mSocket)
|
||||
{
|
||||
apr_status_t status;
|
||||
apr_size_t size;
|
||||
apr_interval_time_t flush_time_left_usec = flush_max_block_time;
|
||||
apr_interval_time_t timeout_usec = flush ? flush_min_timeout : 0;
|
||||
|
||||
LLMutexLock lock(&mOutputMutex);
|
||||
if(!mOutput.empty())
|
||||
while(result && !mOutput.empty())
|
||||
{
|
||||
// write any outgoing messages
|
||||
size = (apr_size_t)mOutput.size();
|
||||
apr_size_t size = (apr_size_t)mOutput.size();
|
||||
|
||||
setSocketTimeout(0);
|
||||
setSocketTimeout(timeout_usec);
|
||||
|
||||
// LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;
|
||||
|
||||
status = apr_socket_send(
|
||||
apr_status_t status = apr_socket_send(
|
||||
mSocket->getSocket(),
|
||||
(const char*)mOutput.data(),
|
||||
&size);
|
||||
@@ -193,12 +209,29 @@ bool LLPluginMessagePipe::pumpOutput()
|
||||
{
|
||||
// success
|
||||
mOutput = mOutput.substr(size);
|
||||
break;
|
||||
}
|
||||
else if(APR_STATUS_IS_EAGAIN(status))
|
||||
else if(APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status))
|
||||
{
|
||||
// Socket buffer is full...
|
||||
// remove the written part from the buffer and try again later.
|
||||
mOutput = mOutput.substr(size);
|
||||
if (!flush)
|
||||
break;
|
||||
flush_time_left_usec -= timeout_usec;
|
||||
if (flush_time_left_usec <= 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else if (size == 0)
|
||||
{
|
||||
// Nothing at all was written. Increment wait time.
|
||||
timeout_usec = std::min(flush_max_timeout, 2 * timeout_usec);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout_usec = std::max(flush_min_timeout, timeout_usec / 2);
|
||||
}
|
||||
}
|
||||
else if(APR_STATUS_IS_EOF(status))
|
||||
{
|
||||
|
||||
@@ -61,6 +61,8 @@ protected:
|
||||
bool canSendMessage(void);
|
||||
// call this to send a message over the pipe
|
||||
bool writeMessageRaw(const std::string &message);
|
||||
// call this to attempt to flush all messages for 10 seconds long.
|
||||
bool flushMessages(void);
|
||||
// call this to close the pipe
|
||||
void killMessagePipe(void);
|
||||
|
||||
@@ -79,8 +81,10 @@ public:
|
||||
void clearOwner(void);
|
||||
|
||||
bool pump(F64 timeout = 0.0f);
|
||||
bool pumpOutput();
|
||||
bool pumpOutput(bool flush = false);
|
||||
bool pumpInput(F64 timeout = 0.0f);
|
||||
|
||||
bool flushMessages(void) { return pumpOutput(true); }
|
||||
|
||||
protected:
|
||||
void processInput(void);
|
||||
|
||||
@@ -556,11 +556,22 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message)
|
||||
}
|
||||
else if (message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
|
||||
{
|
||||
bool flush = false;
|
||||
std::string message_name = parsed.getName();
|
||||
if(message_name == "shutdown")
|
||||
{
|
||||
// The plugin is finished.
|
||||
setState(STATE_UNLOADING);
|
||||
flush = true;
|
||||
}
|
||||
else if (message_name == "flush")
|
||||
{
|
||||
flush = true;
|
||||
passMessage = false;
|
||||
}
|
||||
if (flush)
|
||||
{
|
||||
flushMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
|
||||
mDebug = false;
|
||||
mBlocked = false;
|
||||
mPolledInput = false;
|
||||
mReceivedShutdown = false;
|
||||
mPollFD.client_data = NULL;
|
||||
mPollFDPool.create();
|
||||
|
||||
@@ -165,6 +166,8 @@ void LLPluginProcessParent::errorState(void)
|
||||
{
|
||||
if(mState < STATE_RUNNING)
|
||||
setState(STATE_LAUNCH_FAILURE);
|
||||
else if (mReceivedShutdown)
|
||||
setState(STATE_EXITING);
|
||||
else
|
||||
setState(STATE_ERROR);
|
||||
}
|
||||
@@ -1012,6 +1015,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
|
||||
else if(message_name == "shutdown")
|
||||
{
|
||||
LL_INFOS("Plugin") << "received shutdown message" << LL_ENDL;
|
||||
mReceivedShutdown = true;
|
||||
mOwner->receivedShutdown();
|
||||
}
|
||||
else if(message_name == "shm_add_response")
|
||||
|
||||
@@ -145,8 +145,8 @@ private:
|
||||
STATE_RUNNING, //
|
||||
STATE_LAUNCH_FAILURE, // Failure before plugin loaded
|
||||
STATE_ERROR, // generic bailout state
|
||||
STATE_CLEANUP, // clean everything up
|
||||
STATE_EXITING, // Tried to kill process, waiting for it to exit
|
||||
STATE_CLEANUP, // clean everything up
|
||||
STATE_DONE //
|
||||
|
||||
};
|
||||
@@ -183,6 +183,7 @@ private:
|
||||
bool mDebug;
|
||||
bool mBlocked;
|
||||
bool mPolledInput;
|
||||
bool mReceivedShutdown;
|
||||
|
||||
LLProcessLauncher mDebugger;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user