merge changes for MAINT-5974

master
Oz Linden 2016-04-08 11:32:48 -04:00
commit ed38b5c923
6 changed files with 67 additions and 183 deletions

View File

@ -40,7 +40,6 @@
#include "lldir.h"
#include "llfile.h"
#include "llsdserialize.h"
#include "llsdserialize.h"
#include "llproxy.h"
#include "llcorehttputil.h"
#include "llhttpsdhandler.h"
@ -49,6 +48,7 @@
#include <curl/curl.h>
#include <openssl/crypto.h>
#include <boost/regex.hpp>
BOOL gBreak = false;
BOOL gSent = false;
@ -147,16 +147,16 @@ std::string getStartupStateFromLog(std::string& sllog)
return startup_state;
}
bool LLCrashLogger::readDebugFromXML(LLSD& dest, const std::string& filename )
bool LLCrashLogger::readFromXML(LLSD& dest, const std::string& filename )
{
std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,filename);
std::ifstream debug_log_file(db_file_name.c_str());
std::ifstream log_file(db_file_name.c_str());
// Look for it in the debug_info.log file
if (debug_log_file.is_open())
// Look for it in the given file
if (log_file.is_open())
{
LLSDSerialize::fromXML(dest, debug_log_file);
debug_log_file.close();
LLSDSerialize::fromXML(dest, log_file);
log_file.close();
return true;
}
return false;
@ -200,9 +200,16 @@ void LLCrashLogger::gatherFiles()
LLSD static_sd;
LLSD dynamic_sd;
//if we ever want to change the endpoint we send crashes to
//we can construct a file download ( a la feature table filename for example)
//containing the new endpoint
LLSD endpoint;
std::string grid;
std::string fqdn;
bool has_logs = readDebugFromXML( static_sd, "static_debug_info.log" );
has_logs |= readDebugFromXML( dynamic_sd, "dynamic_debug_info.log" );
bool has_logs = readFromXML( static_sd, "static_debug_info.log" );
has_logs |= readFromXML( dynamic_sd, "dynamic_debug_info.log" );
if ( has_logs )
{
@ -212,6 +219,7 @@ void LLCrashLogger::gatherFiles()
mFileMap["SecondLifeLog"] = mDebugLog["SLLog"].asString();
mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString();
mFileMap["CrashHostUrl"] = loadCrashURLSetting();
if(mDebugLog.has("CAFilename"))
{
LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE,
@ -243,31 +251,14 @@ void LLCrashLogger::gatherFiles()
gatherPlatformSpecificFiles();
//Use the debug log to reconstruct the URL to send the crash report to
if(mDebugLog.has("CrashHostUrl"))
{
// Crash log receiver has been manually configured.
mCrashHost = mDebugLog["CrashHostUrl"].asString();
}
else if(mDebugLog.has("CurrentSimHost"))
{
mCrashHost = "https://";
mCrashHost += mDebugLog["CurrentSimHost"].asString();
mCrashHost += ":12043/crash/report";
}
else if(mDebugLog.has("GridName"))
{
// This is a 'little' hacky, but its the best simple solution.
std::string grid_host = mDebugLog["GridName"].asString();
LLStringUtil::toLower(grid_host);
mCrashHost = "https://login.";
mCrashHost += grid_host;
mCrashHost += ".lindenlab.com:12043/crash/report";
}
if ( has_logs && (mFileMap["CrashHostUrl"] != "") )
{
mCrashHost = mFileMap["CrashHostUrl"];
}
// Use login servers as the alternate, since they are already load balanced and have a known name
mAltCrashHost = "https://login.agni.lindenlab.com:12043/crash/report";
//default to agni, per product
mAltCrashHost = "http://viewercrashreport.agni.lindenlab.com/cgi-bin/viewercrashreceiver.py";
mCrashInfo["DebugLog"] = mDebugLog;
mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"stats.log");
@ -352,8 +343,9 @@ LLSD LLCrashLogger::constructPostData()
const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml";
S32 LLCrashLogger::loadCrashBehaviorSetting()
std::string LLCrashLogger::loadCrashURLSetting()
{
// First check user_settings (in the user's home dir)
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
if (! mCrashSettings.loadFromFile(filename))
@ -363,38 +355,14 @@ S32 LLCrashLogger::loadCrashBehaviorSetting()
mCrashSettings.loadFromFile(filename);
}
// If we didn't load any files above, this will return the default
S32 value = mCrashSettings.getS32("CrashSubmitBehavior");
// Whatever value we got, make sure it's valid
switch (value)
{
case CRASH_BEHAVIOR_NEVER_SEND:
return CRASH_BEHAVIOR_NEVER_SEND;
case CRASH_BEHAVIOR_ALWAYS_SEND:
return CRASH_BEHAVIOR_ALWAYS_SEND;
}
return CRASH_BEHAVIOR_ASK;
}
bool LLCrashLogger::saveCrashBehaviorSetting(S32 crash_behavior)
{
switch (crash_behavior)
{
case CRASH_BEHAVIOR_ASK:
case CRASH_BEHAVIOR_NEVER_SEND:
case CRASH_BEHAVIOR_ALWAYS_SEND:
break;
default:
return false;
}
mCrashSettings.setS32("CrashSubmitBehavior", crash_behavior);
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
mCrashSettings.saveToFile(filename, FALSE);
return true;
if (! mCrashSettings.controlExists("CrashHostUrl"))
{
return "";
}
else
{
return mCrashSettings.getString("CrashHostUrl");
}
}
bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout)
@ -402,7 +370,6 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
gBreak = false;
httpOpts->setTimeout(timeout);
for(int i = 0; i < retries; ++i)
@ -421,10 +388,11 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
}
while(!gBreak)
{
updateApplication(); // No new message, just pump the IO
{
ms_sleep(250);
updateApplication(); // No new message, just pump the IO
httpRequest->update(0L);
}
}
if(gSent)
{
return gSent;
@ -437,12 +405,13 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
bool LLCrashLogger::sendCrashLog(std::string dump_dir)
{
gDirUtilp->setDumpDir( dump_dir );
std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLifeCrashReport");
std::string report_file = dump_path + ".log";
gatherFiles();
LLSD post_data;
@ -452,19 +421,26 @@ bool LLCrashLogger::sendCrashLog(std::string dump_dir)
std::ofstream out_file(report_file.c_str());
LLSDSerialize::toPrettyXML(post_data, out_file);
out_file.flush();
out_file.close();
bool sent = false;
//*TODO: Translate
updateApplication("DEBUG: crash host in send logs "+mCrashHost);
if(mCrashHost != "")
{
{
std::string msg = "Using derived crash server... ";
msg = msg+mCrashHost.c_str();
updateApplication(msg.c_str());
sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5);
}
if(!sent)
{
sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to alternate server"), 3, 5);
updateApplication("Using default server...");
sent = runCrashLogPost(mAltCrashHost, post_data, std::string("Sending to default server"), 3, 5);
}
mSentCrashLogs = sent;
@ -475,66 +451,21 @@ bool LLCrashLogger::sendCrashLog(std::string dump_dir)
bool LLCrashLogger::sendCrashLogs()
{
//pertinent code from below moved into a subroutine.
LLSD locks = mKeyMaster.getProcessList();
LLSD newlocks = LLSD::emptyArray();
LLSD opts = getOptionData(PRIORITY_COMMAND_LINE);
LLSD rec;
if ( opts.has("pid") && opts.has("dumpdir") && opts.has("procname") )
if ( opts.has("dumpdir") )
{
rec["pid"]=opts["pid"];
rec["dumpdir"]=opts["dumpdir"];
rec["procname"]=opts["procname"];
}
if (locks.isArray())
else
{
for (LLSD::array_iterator lock=locks.beginArray();
lock !=locks.endArray();
++lock)
{
if ( (*lock).has("pid") && (*lock).has("dumpdir") && (*lock).has("procname") )
{
if ( mKeyMaster.isProcessAlive( (*lock)["pid"].asInteger(), (*lock)["procname"].asString() ) )
{
newlocks.append(*lock);
}
else
{
//TODO: This is a hack but I didn't want to include boost in another file or retest everything related to lldir
if (LLCrashLock::fileExists((*lock)["dumpdir"].asString()))
{
//the viewer cleans up the log directory on clean shutdown
//but is ignorant of the locking table.
if (!sendCrashLog((*lock)["dumpdir"].asString()))
{
newlocks.append(*lock); //Failed to send log so don't delete it.
}
else
{
//mCrashInfo["DebugLog"].erase("MinidumpPath");
return false;
}
mKeyMaster.cleanupProcess((*lock)["dumpdir"].asString());
}
}
}
}
else
{
LL_WARNS() << "Discarding corrupted entry from lock table." << LL_ENDL;
}
}
}
if (rec)
{
newlocks.append(rec);
}
mKeyMaster.putProcessList(newlocks);
return true;
return sendCrashLog(rec["dumpdir"].asString());
}
void LLCrashLogger::updateApplication(const std::string& message)
@ -567,25 +498,7 @@ bool LLCrashLogger::init()
// Set the log file to crashreport.log
LLError::logToFile(log_file); //NOTE: Until this line, LL_INFOS LL_WARNS, etc are blown to the ether.
// Handle locking
bool locked = mKeyMaster.requestMaster(); //Request master locking file. wait time is defaulted to 300S
while (!locked && mKeyMaster.isWaiting())
{
LL_INFOS("CRASHREPORT") << "Waiting for lock." << LL_ENDL;
#if LL_WINDOWS
Sleep(1000);
#else
sleep(1);
#endif
locked = mKeyMaster.checkMaster();
}
if (!locked)
{
LL_WARNS("CRASHREPORT") << "Unable to get master lock. Another crash reporter may be hung." << LL_ENDL;
return false;
}
LL_INFOS() << "Crash reporter file rotation complete." << LL_ENDL;
mCrashSettings.declareS32("CrashSubmitBehavior", CRASH_BEHAVIOR_ALWAYS_SEND,
"Controls behavior when viewer crashes "
@ -595,14 +508,7 @@ bool LLCrashLogger::init()
// LL_INFOS() << "Loading crash behavior setting" << LL_ENDL;
// mCrashBehavior = loadCrashBehaviorSetting();
// If user doesn't want to send, bail out
if (mCrashBehavior == CRASH_BEHAVIOR_NEVER_SEND)
{
LL_INFOS() << "Crash behavior is never_send, quitting" << LL_ENDL;
return false;
}
init_curl();
LLCore::HttpRequest::createService();
LLCore::HttpRequest::startThread();

View File

@ -46,13 +46,12 @@ class LLCrashLogger : public LLApp
public:
LLCrashLogger();
virtual ~LLCrashLogger();
S32 loadCrashBehaviorSetting();
bool readDebugFromXML(LLSD& dest, const std::string& filename );
std::string loadCrashURLSetting();
bool readFromXML(LLSD& dest, const std::string& filename );
void gatherFiles();
void mergeLogs( LLSD src_sd );
virtual void gatherPlatformSpecificFiles() {}
bool saveCrashBehaviorSetting(S32 crash_behavior);
bool sendCrashLog(std::string dump_dir);
bool sendCrashLogs();
LLSD constructPostData();

View File

@ -66,22 +66,19 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()
bool LLCrashLoggerMac::mainLoop()
{
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
{
gSendReport = true;
}
if(gRememberChoice)
{
if(gSendReport) saveCrashBehaviorSetting(CRASH_BEHAVIOR_ALWAYS_SEND);
else saveCrashBehaviorSetting(CRASH_BEHAVIOR_NEVER_SEND);
}
if(gSendReport)
{
setUserText(gUserNotes);
sendCrashLogs();
}
LL_INFOS() << "Sending of logs complete" << LL_ENDL;
return true;
}

View File

@ -39,16 +39,17 @@ int main(int argc, char **argv)
LLSD options = LLApp::instance()->getOptionData(
LLApp::PRIORITY_COMMAND_LINE);
if (!(options.has("pid") && options.has("dumpdir")))
{
LL_WARNS() << "Insufficient parameters to crash report." << LL_ENDL;
}
if (! app.init())
{
LL_WARNS() << "Unable to initialize application." << LL_ENDL;
return 1;
}
if (!(options.has("pid") && options.has("dumpdir")))
{
LL_WARNS() << "Insufficient parameters to crash report." << llendl;
}
if (app.getCrashBehavior() != CRASH_BEHAVIOR_ALWAYS_SEND)
{
// return NSApplicationMain(argc, (const char **)argv);

View File

@ -83,10 +83,6 @@ static void exceptionTerminateHandler()
bool initViewer()
{
#if LL_SOLARIS && defined(__sparc)
asm ("ta\t6"); // NOTE: Make sure memory alignment is enforced on SPARC
#endif
// Set the working dir to <bundle>/Contents/Resources
if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1)
{
@ -301,6 +297,7 @@ void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
std::string appname = gDirUtilp->getExecutableFilename();
std::string str[] = { "-pid", pid_str.str(), "-dumpdir", logdir, "-procname", appname.c_str() };
std::vector< std::string > args( str, str + ( sizeof ( str ) / sizeof ( std::string ) ) );
LL_WARNS() << "about to launch mac-crash-logger" << pid_str << " " << logdir << " " << appname << LL_ENDL;
launchApplication(&command_str, &args);
}

View File

@ -171,22 +171,6 @@ bool handle_button_click(WORD button_id)
return false;
}
// See if "do this next time" is checked and save state
S32 crash_behavior = CRASH_BEHAVIOR_ASK;
LRESULT result = SendDlgItemMessage(gHwndReport, IDC_CHECK_AUTO, BM_GETCHECK, 0, 0);
if (result == BST_CHECKED)
{
if (button_id == IDOK)
{
crash_behavior = CRASH_BEHAVIOR_ALWAYS_SEND;
}
else if (button_id == IDCANCEL)
{
crash_behavior = CRASH_BEHAVIOR_NEVER_SEND;
}
((LLCrashLoggerWindows*)LLCrashLogger::instance())->saveCrashBehaviorSetting(crash_behavior);
}
// We're done with this dialog.
gFirstDialog = FALSE;