Breakpad: Commence nuclear bombardment of the unused stuff
Windows breakpad crash reports implemented and uploaded TODO: llappviewer linux and mac port of breakpad3
This commit is contained in:
@@ -75,7 +75,6 @@ if (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
|
||||
endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
|
||||
|
||||
add_custom_target(viewer)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llui)
|
||||
|
||||
@@ -87,28 +86,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}plugins)
|
||||
# add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
|
||||
#endif (NOT LINUX)
|
||||
|
||||
if (LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
|
||||
add_dependencies(viewer linux-crash-logger-strip-target)
|
||||
elseif (DARWIN)
|
||||
#add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
|
||||
#add_subdirectory(${VIEWER_PREFIX}mac_updater)
|
||||
add_dependencies(viewer mac-crash-logger)
|
||||
#add_dependencies(viewer mac-updater)
|
||||
elseif (WINDOWS)
|
||||
add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
|
||||
# cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
|
||||
if (EXISTS ${VIEWER_DIR}win_setup)
|
||||
add_subdirectory(${VIEWER_DIR}win_setup)
|
||||
endif (EXISTS ${VIEWER_DIR}win_setup)
|
||||
add_subdirectory(${VIEWER_PREFIX}win_updater)
|
||||
add_dependencies(viewer windows-updater)
|
||||
add_dependencies(viewer windows-crash-logger)
|
||||
elseif (SOLARIS)
|
||||
add_subdirectory(solaris_crash_logger)
|
||||
add_dependencies(viewer solaris-crash-logger)
|
||||
endif (LINUX)
|
||||
|
||||
add_subdirectory(${VIEWER_PREFIX}newview/statemachine)
|
||||
add_subdirectory(${VIEWER_PREFIX}newview)
|
||||
add_dependencies(viewer secondlife-bin)
|
||||
|
||||
@@ -61,7 +61,6 @@ set(cmake_SOURCE_FILES
|
||||
LLAudio.cmake
|
||||
LLCharacter.cmake
|
||||
LLCommon.cmake
|
||||
LLCrashLogger.cmake
|
||||
LLImage.cmake
|
||||
LLImageJ2COJ.cmake
|
||||
LLInventory.cmake
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
set(LLCRASHLOGGER_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llcrashlogger
|
||||
)
|
||||
|
||||
set(LLCRASHLOGGER_LIBRARIES llcrashlogger)
|
||||
@@ -1,72 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
project(linux_crash_logger)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLCrashLogger)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
include(LLXML)
|
||||
include(Linking)
|
||||
include(UI)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLCRASHLOGGER_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(linux_crash_logger_SOURCE_FILES
|
||||
linux_crash_logger.cpp
|
||||
llcrashloggerlinux.cpp
|
||||
)
|
||||
|
||||
set(linux_crash_logger_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llcrashloggerlinux.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${linux_crash_logger_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND linux_crash_logger_SOURCE_FILES
|
||||
${linux_crash_logger_HEADER_FILES}
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
|
||||
|
||||
add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(linux-crash-logger
|
||||
${LLCRASHLOGGER_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLXML_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLUI_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${UI_LIBRARIES}
|
||||
${DB_LIBRARIES}
|
||||
${XMLRPCEPI_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${APRUTIL_LIBRARIES}
|
||||
${CRYPTO_LIBRARIES}
|
||||
rt
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT linux-crash-logger-stripped
|
||||
COMMAND strip
|
||||
ARGS --strip-debug -o linux-crash-logger-stripped linux-crash-logger
|
||||
DEPENDS linux-crash-logger
|
||||
)
|
||||
|
||||
add_custom_target(linux-crash-logger-strip-target ALL
|
||||
DEPENDS linux-crash-logger-stripped)
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* @file linux_crash_logger.cpp
|
||||
* @brief Linux crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2003-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llcrashloggerlinux.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
LLCrashLoggerLinux app;
|
||||
app.parseCommandOptions(argc, argv);
|
||||
app.init();
|
||||
app.mainLoop();
|
||||
app.cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/**
|
||||
* @file llcrashloggerlinux.cpp
|
||||
* @brief Linux crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2003-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llcrashloggerlinux.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "boost/tokenizer.hpp"
|
||||
|
||||
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
|
||||
#include "llerror.h"
|
||||
#include "llfile.h"
|
||||
#include "lltimer.h"
|
||||
#include "llstring.h"
|
||||
#include "lldir.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
#if LL_GTK
|
||||
# include "gtk/gtk.h"
|
||||
#endif // LL_GTK
|
||||
|
||||
#define MAX_LOADSTRING 100
|
||||
|
||||
// These need to be localized.
|
||||
static const char dialog_text[] =
|
||||
"Second Life appears to have crashed or frozen last time it ran.\n"
|
||||
"This crash reporter collects information about your computer's hardware, operating system, and some Second Life logs, all of which are used for debugging purposes only.\n"
|
||||
"\n"
|
||||
"Send crash report?";
|
||||
|
||||
static const char dialog_title[] =
|
||||
"Second Life Crash Logger";
|
||||
|
||||
#if LL_GTK
|
||||
static void response_callback (GtkDialog *dialog,
|
||||
gint arg1,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint *response = (gint*)user_data;
|
||||
*response = arg1;
|
||||
gtk_widget_destroy(GTK_WIDGET(dialog));
|
||||
gtk_main_quit();
|
||||
}
|
||||
#endif // LL_GTK
|
||||
|
||||
static BOOL do_ask_dialog(void)
|
||||
{
|
||||
#if LL_GTK
|
||||
gtk_disable_setlocale();
|
||||
if (!gtk_init_check(NULL, NULL)) {
|
||||
llinfos << "Could not initialize GTK for 'ask to send crash report' dialog; not sending report." << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkWidget *win = NULL;
|
||||
GtkDialogFlags flags = GTK_DIALOG_MODAL;
|
||||
GtkMessageType messagetype = GTK_MESSAGE_QUESTION;
|
||||
GtkButtonsType buttons = GTK_BUTTONS_YES_NO;
|
||||
gint response = GTK_RESPONSE_NONE;
|
||||
|
||||
win = gtk_message_dialog_new(NULL,
|
||||
flags, messagetype, buttons,
|
||||
"%s", dialog_text);
|
||||
gtk_window_set_type_hint(GTK_WINDOW(win),
|
||||
GDK_WINDOW_TYPE_HINT_DIALOG);
|
||||
gtk_window_set_title(GTK_WINDOW(win), dialog_title);
|
||||
g_signal_connect (win,
|
||||
"response",
|
||||
G_CALLBACK (response_callback),
|
||||
&response);
|
||||
gtk_widget_show_all (win);
|
||||
gtk_main();
|
||||
|
||||
return (GTK_RESPONSE_OK == response ||
|
||||
GTK_RESPONSE_YES == response ||
|
||||
GTK_RESPONSE_APPLY == response);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif // LL_GTK
|
||||
}
|
||||
|
||||
LLCrashLoggerLinux::LLCrashLoggerLinux(void)
|
||||
{
|
||||
}
|
||||
|
||||
LLCrashLoggerLinux::~LLCrashLoggerLinux(void)
|
||||
{
|
||||
}
|
||||
|
||||
void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
|
||||
{
|
||||
mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log").c_str();
|
||||
}
|
||||
|
||||
bool LLCrashLoggerLinux::mainLoop()
|
||||
{
|
||||
bool send_logs = true;
|
||||
if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
|
||||
{
|
||||
send_logs = do_ask_dialog();
|
||||
}
|
||||
else if(CRASH_BEHAVIOR_NEVER_SEND == getCrashBehavior())
|
||||
{
|
||||
send_logs = false;
|
||||
}
|
||||
|
||||
if(send_logs)
|
||||
{
|
||||
sendCrashLogs();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLCrashLoggerLinux::updateApplication(const std::string& message)
|
||||
{
|
||||
LLCrashLogger::updateApplication(message);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* @file llcrashloggerlinux.h
|
||||
* @brief Linux crash logger definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2003-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLCRASHLOGGERLINUX_H
|
||||
#define LLCRASHLOGGERLINUX_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llcrashlogger.h"
|
||||
#include "llstring.h"
|
||||
|
||||
class LLCrashLoggerLinux : public LLCrashLogger
|
||||
{
|
||||
public:
|
||||
LLCrashLoggerLinux(void);
|
||||
~LLCrashLoggerLinux(void);
|
||||
virtual bool mainLoop();
|
||||
virtual void updateApplication(const std::string& = LLStringUtil::null);
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
project(llcrashlogger)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
include(LLXML)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLMESSAGE_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llcrashlogger_SOURCE_FILES
|
||||
llcrashlogger.cpp
|
||||
llcrashlock.cpp
|
||||
)
|
||||
|
||||
set(llcrashlogger_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llcrashlogger.h
|
||||
llcrashlock.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${llcrashlogger_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND llcrashlogger_SOURCE_FILES ${llcrashlogger_HEADER_FILES})
|
||||
|
||||
add_library(llcrashlogger ${llcrashlogger_SOURCE_FILES})
|
||||
add_dependencies(llcrashlogger prepare)
|
||||
@@ -1,211 +0,0 @@
|
||||
/**
|
||||
* @file llformat.cpp
|
||||
* @date January 2007
|
||||
* @brief string formatting utility
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llcrashlock.h"
|
||||
#include "lldir.h"
|
||||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llnametable.h"
|
||||
#include "llframetimer.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#if LL_WINDOWS //For windows platform.
|
||||
#include <windows.h>
|
||||
#include <TlHelp32.h>
|
||||
|
||||
/*
|
||||
namespace {
|
||||
inline DWORD getpid() {
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool LLCrashLock::isProcessAlive(U32 pid, const std::string& pname)
|
||||
{
|
||||
std::wstring wpname;
|
||||
wpname = std::wstring(pname.begin(), pname.end());
|
||||
|
||||
HANDLE snapshot;
|
||||
PROCESSENTRY32 pe32;
|
||||
|
||||
bool matched = false;
|
||||
|
||||
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (snapshot == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
if (Process32First(snapshot, &pe32))
|
||||
{
|
||||
do {
|
||||
std::wstring wexecname = pe32.szExeFile;
|
||||
std::string execname = std::string(wexecname.begin(), wexecname.end());
|
||||
if (!wpname.compare(pe32.szExeFile))
|
||||
{
|
||||
if (pid == (U32)pe32.th32ProcessID)
|
||||
{
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (Process32Next(snapshot, &pe32));
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(snapshot);
|
||||
return matched;
|
||||
}
|
||||
|
||||
#else //Everyone Else
|
||||
bool LLCrashLock::isProcessAlive(U32 pid, const std::string& pname)
|
||||
{
|
||||
//Will boost.process ever become a reality?
|
||||
std::stringstream cmd;
|
||||
|
||||
cmd << "pgrep '" << pname << "' | grep '^" << pid << "$'";
|
||||
return (!system(cmd.str().c_str()));
|
||||
}
|
||||
#endif //Everyone else.
|
||||
|
||||
|
||||
LLCrashLock::LLCrashLock() : mCleanUp(true), mWaitingPID(0)
|
||||
{
|
||||
}
|
||||
|
||||
void LLCrashLock::setCleanUp(bool cleanup)
|
||||
{
|
||||
mCleanUp = cleanup; //Allow cleanup to be disabled for debugging.
|
||||
}
|
||||
|
||||
LLSD LLCrashLock::getLockFile(std::string filename)
|
||||
{
|
||||
LLSD lock_sd = LLSD::emptyMap();
|
||||
|
||||
llifstream ifile(filename);
|
||||
|
||||
if (ifile.is_open())
|
||||
{
|
||||
LLSDSerialize::fromXML(lock_sd, ifile);
|
||||
ifile.close();
|
||||
}
|
||||
|
||||
return lock_sd;
|
||||
}
|
||||
|
||||
bool LLCrashLock::putLockFile(std::string filename, const LLSD& data)
|
||||
{
|
||||
bool result = true;
|
||||
llofstream ofile(filename);
|
||||
|
||||
if (!LLSDSerialize::toXML(data,ofile))
|
||||
{
|
||||
result=false;
|
||||
}
|
||||
ofile.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LLCrashLock::requestMaster( F32 timeout )
|
||||
{
|
||||
if (mMaster.empty())
|
||||
{
|
||||
mMaster = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
|
||||
"crash_master.lock");
|
||||
}
|
||||
|
||||
LLSD lock_sd=getLockFile(mMaster);
|
||||
|
||||
if (lock_sd.has("pid"))
|
||||
{
|
||||
mWaitingPID = lock_sd["pid"].asInteger();
|
||||
if ( isProcessAlive(mWaitingPID, gDirUtilp->getExecutableFilename()) )
|
||||
{
|
||||
mTimer.resetWithExpiry(timeout);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
U32 pid = getpid();
|
||||
lock_sd["pid"] = (LLSD::Integer)pid;
|
||||
return putLockFile(mMaster,lock_sd);
|
||||
}
|
||||
|
||||
bool LLCrashLock::checkMaster()
|
||||
{
|
||||
if (mWaitingPID)
|
||||
{
|
||||
return (!isProcessAlive(mWaitingPID, gDirUtilp->getExecutableFilename()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLCrashLock::isWaiting()
|
||||
{
|
||||
return !mTimer.hasExpired();
|
||||
}
|
||||
|
||||
void LLCrashLock::releaseMaster()
|
||||
{
|
||||
//Yeeeeeeehaw
|
||||
unlink(mMaster.c_str());
|
||||
}
|
||||
|
||||
LLSD LLCrashLock::getProcessList()
|
||||
{
|
||||
if (mDumpTable.empty())
|
||||
{
|
||||
mDumpTable= gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
|
||||
"crash_table.lock");
|
||||
}
|
||||
return getLockFile(mDumpTable);
|
||||
}
|
||||
|
||||
//static
|
||||
bool LLCrashLock::fileExists(std::string filename)
|
||||
{
|
||||
return boost::filesystem::exists(filename.c_str());
|
||||
}
|
||||
|
||||
void LLCrashLock::cleanupProcess(std::string proc_dir)
|
||||
{
|
||||
boost::filesystem::remove_all(proc_dir);
|
||||
}
|
||||
|
||||
bool LLCrashLock::putProcessList(const LLSD& proc_sd)
|
||||
{
|
||||
return putLockFile(mDumpTable,proc_sd);
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* @file llpidlock.h
|
||||
* @brief Maintainence of disk locking files for crash reporting
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_CRASHLOCK_H
|
||||
#define LL_CRASHLOCK_H
|
||||
|
||||
#include "llframetimer.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
#if !LL_WINDOWS //For non-windows platforms.
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
//Crash reporter will now be kicked off by the viewer but otherwise
|
||||
//run independent of the viewer.
|
||||
|
||||
class LLCrashLock
|
||||
{
|
||||
public:
|
||||
LLCrashLock();
|
||||
bool requestMaster( F32 timeout=300.0); //Wait until timeout for master lock.
|
||||
bool checkMaster(); //True if available. False if not.
|
||||
void releaseMaster( ); //Release master lockfile.
|
||||
bool isLockPresent(std::string filename); //Check if lockfile exists.
|
||||
bool isProcessAlive(U32 pid, const std::string& pname); //Check if pid is alive.
|
||||
bool isWaiting(); //Waiting for master lock to be released.
|
||||
LLSD getProcessList(); //Get next process pid/dir pairs
|
||||
void cleanupProcess(std::string proc_dir); //Remove from list, clean up working dir.
|
||||
bool putProcessList(const LLSD& processlist); //Write pid/dir pairs back to disk.
|
||||
static bool fileExists(std::string filename);
|
||||
|
||||
|
||||
//getters
|
||||
S32 getPID();
|
||||
|
||||
//setters
|
||||
void setCleanUp(bool cleanup=true);
|
||||
void setSaveName(std::string savename);
|
||||
private:
|
||||
LLSD getLockFile(std::string filename);
|
||||
bool putLockFile(std::string filename, const LLSD& data);
|
||||
bool mCleanUp;
|
||||
std::string mMaster;
|
||||
std::string mDumpTable;
|
||||
U32 mWaitingPID; //The process we're waiting on if any.
|
||||
LLFrameTimer mTimer;
|
||||
};
|
||||
|
||||
#endif // LL_CRASHLOCK_H
|
||||
@@ -1,76 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
project(mac_crash_logger)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLCrashLogger)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
include(LLXML)
|
||||
include(Linking)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLCRASHLOGGER_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(mac_crash_logger_SOURCE_FILES
|
||||
mac_crash_logger.cpp
|
||||
llcrashloggermac.cpp
|
||||
)
|
||||
|
||||
set(mac_crash_logger_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llcrashloggermac.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${mac_crash_logger_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
list(APPEND mac_crash_logger_SOURCE_FILES ${mac_crash_logger_HEADER_FILES})
|
||||
|
||||
set(mac_crash_logger_RESOURCE_FILES
|
||||
CrashReporter.nib/
|
||||
)
|
||||
set_source_files_properties(
|
||||
${mac_crash_logger_RESOURCE_FILES}
|
||||
PROPERTIES
|
||||
HEADER_FILE_ONLY TRUE
|
||||
)
|
||||
SOURCE_GROUP("Resources" FILES ${mac_crash_logger_RESOURCE_FILES})
|
||||
list(APPEND mac_crash_logger_SOURCE_FILES ${mac_crash_logger_RESOURCE_FILES})
|
||||
|
||||
add_executable(mac-crash-logger
|
||||
MACOSX_BUNDLE
|
||||
${mac_crash_logger_SOURCE_FILES})
|
||||
|
||||
set_target_properties(mac-crash-logger
|
||||
PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
)
|
||||
|
||||
target_link_libraries(mac-crash-logger
|
||||
${LLCRASHLOGGER_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLXML_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET mac-crash-logger POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
-E
|
||||
copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CrashReporter.nib
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-crash-logger.app/Contents/Resources/CrashReporter.nib
|
||||
)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
18
indra/mac_crash_logger/CrashReporter.nib/info.nib
generated
18
indra/mac_crash_logger/CrashReporter.nib/info.nib
generated
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>629</string>
|
||||
<key>IBLastKnownRelativeProjectPath</key>
|
||||
<string>../../build-darwin-i386/SecondLife.xcodeproj</string>
|
||||
<key>IBOldestOS</key>
|
||||
<integer>5</integer>
|
||||
<key>IBOpenObjects</key>
|
||||
<array/>
|
||||
<key>IBSystem Version</key>
|
||||
<string>9E17</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCarbonFramework</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,68 +0,0 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<object class="NSIBObjectData">
|
||||
<object name="rootObject" class="NSCustomObject" id="1">
|
||||
</object>
|
||||
<array count="7" name="allObjects">
|
||||
<object class="IBCarbonButton" id="182">
|
||||
<ostype name="command">ok </ostype>
|
||||
<string name="title">Send Report</string>
|
||||
<string name="bounds">414 273 434 378 </string>
|
||||
</object>
|
||||
<object class="IBCarbonButton" id="183">
|
||||
<ostype name="command">not!</ostype>
|
||||
<int name="buttonType">2</int>
|
||||
<string name="title">Don't Send</string>
|
||||
<string name="bounds">414 390 434 487 </string>
|
||||
</object>
|
||||
<object class="IBCarbonStaticText" id="181">
|
||||
<string name="title">Second Life appears to have crashed or frozen the last time it ran. This crash reporter collects information about your computer's hardware configuration, operating system, and some Second Life logs, all of which are used for debugging purposes only. In the space below, please briefly describe what you were doing or trying to do just prior to the crash. Thank you for your help! This report is NOT read by Customer Support. If you have billing or other questions, please go to: http://www.secondlife.com/support/ If you don't wish to send Linden Lab a crash report, press Cancel. </string>
|
||||
<string name="bounds">20 20 231 487 </string>
|
||||
</object>
|
||||
<object class="IBCarbonWindow" id="166">
|
||||
<int name="carbonWindowClass">2</int>
|
||||
<int name="themeBrush">3</int>
|
||||
<int name="windowPosition">7</int>
|
||||
<string name="title">Second Life Crash Logger</string>
|
||||
<object name="rootControl" class="IBCarbonRootControl" id="167">
|
||||
<array count="5" name="subviews">
|
||||
<reference idRef="181"/>
|
||||
<reference idRef="182"/>
|
||||
<reference idRef="183"/>
|
||||
<object class="IBCarbonEditText" id="185">
|
||||
<ostype name="controlSignature">text</ostype>
|
||||
<boolean name="isUnicode">TRUE</boolean>
|
||||
<string name="bounds">242 23 391 484 </string>
|
||||
</object>
|
||||
<object class="IBCarbonCheckBox" id="193">
|
||||
<ostype name="controlSignature">remb</ostype>
|
||||
<string name="title">Remember This Choice</string>
|
||||
<string name="bounds">415 20 433 186 </string>
|
||||
</object>
|
||||
</array>
|
||||
<string name="bounds">0 0 454 507 </string>
|
||||
</object>
|
||||
<string name="windowRect">257 653 711 1160 </string>
|
||||
<string name="ScreenRectAtEncodeTime">0 0 768 1024 </string>
|
||||
</object>
|
||||
<reference idRef="185"/>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="193"/>
|
||||
</array>
|
||||
<array count="7" name="allParents">
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="1"/>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="166"/>
|
||||
<reference idRef="167"/>
|
||||
</array>
|
||||
<dictionary count="2" name="nameTable">
|
||||
<string>CrashReporter</string>
|
||||
<reference idRef="166"/>
|
||||
<string>File's Owner</string>
|
||||
<reference idRef="1"/>
|
||||
</dictionary>
|
||||
<string name="targetFramework">IBCarbonFramework</string>
|
||||
<unsigned_int name="nextObjectID">194</unsigned_int>
|
||||
</object>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>mac-crash-logger</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.secondlife.indra.crashreporter</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string></string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,345 +0,0 @@
|
||||
/**
|
||||
* @file llcrashloggermac.cpp
|
||||
* @brief Mac OSX crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2003-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#include "llcrashloggermac.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "boost/tokenizer.hpp"
|
||||
|
||||
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
|
||||
#include "llerror.h"
|
||||
#include "llfile.h"
|
||||
#include "lltimer.h"
|
||||
#include "llstring.h"
|
||||
#include "lldir.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
#define MAX_LOADSTRING 100
|
||||
const char* const SETTINGS_FILE_HEADER = "version";
|
||||
const S32 SETTINGS_FILE_VERSION = 101;
|
||||
|
||||
// Windows Message Handlers
|
||||
|
||||
BOOL gFirstDialog = TRUE; // Are we currently handling the Send/Don't Send dialog?
|
||||
LLFILE *gDebugFile = NULL;
|
||||
|
||||
WindowRef gWindow = NULL;
|
||||
EventHandlerRef gEventHandler = NULL;
|
||||
std::string gUserNotes = "";
|
||||
bool gSendReport = false;
|
||||
bool gRememberChoice = false;
|
||||
IBNibRef nib = NULL;
|
||||
|
||||
OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
|
||||
{
|
||||
OSStatus result = eventNotHandledErr;
|
||||
OSStatus err;
|
||||
UInt32 evtClass = GetEventClass(event);
|
||||
UInt32 evtKind = GetEventKind(event);
|
||||
if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
|
||||
{
|
||||
HICommand cmd;
|
||||
err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
|
||||
|
||||
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
//Get the value of the checkbox
|
||||
ControlID id;
|
||||
ControlRef checkBox = NULL;
|
||||
id.signature = 'remb';
|
||||
id.id = 0;
|
||||
err = GetControlByID(gWindow, &id, &checkBox);
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
if(GetControl32BitValue(checkBox) == kControlCheckBoxCheckedValue)
|
||||
{
|
||||
gRememberChoice = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gRememberChoice = false;
|
||||
}
|
||||
}
|
||||
switch(cmd.commandID)
|
||||
{
|
||||
case kHICommandOK:
|
||||
{
|
||||
char buffer[65535]; /* Flawfinder: ignore */
|
||||
Size size = sizeof(buffer) - 1;
|
||||
ControlRef textField = NULL;
|
||||
|
||||
id.signature = 'text';
|
||||
id.id = 0;
|
||||
|
||||
err = GetControlByID(gWindow, &id, &textField);
|
||||
if(err == noErr)
|
||||
{
|
||||
// Get the user response text
|
||||
err = GetControlData(textField, kControlNoPart, kControlEditTextTextTag, size, (Ptr)buffer, &size);
|
||||
}
|
||||
if(err == noErr)
|
||||
{
|
||||
// Make sure the string is terminated.
|
||||
buffer[size] = 0;
|
||||
gUserNotes = buffer;
|
||||
|
||||
llinfos << buffer << llendl;
|
||||
}
|
||||
|
||||
// Send the report.
|
||||
|
||||
QuitAppModalLoopForWindow(gWindow);
|
||||
gSendReport = true;
|
||||
result = noErr;
|
||||
}
|
||||
break;
|
||||
|
||||
case kHICommandCancel:
|
||||
QuitAppModalLoopForWindow(gWindow);
|
||||
result = noErr;
|
||||
break;
|
||||
default:
|
||||
result = eventNotHandledErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
LLCrashLoggerMac::LLCrashLoggerMac(void)
|
||||
{
|
||||
}
|
||||
|
||||
LLCrashLoggerMac::~LLCrashLoggerMac(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::init(void)
|
||||
{
|
||||
bool ok = LLCrashLogger::init();
|
||||
if(!ok) return false;
|
||||
if(mCrashBehavior != CRASH_BEHAVIOR_ASK) return true;
|
||||
|
||||
// Real UI...
|
||||
OSStatus err;
|
||||
|
||||
err = CreateNibReference(CFSTR("CrashReporter"), &nib);
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
err = CreateWindowFromNib(nib, CFSTR("CrashReporter"), &gWindow);
|
||||
}
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
// Set focus to the edit text area
|
||||
ControlRef textField = NULL;
|
||||
ControlID id;
|
||||
|
||||
id.signature = 'text';
|
||||
id.id = 0;
|
||||
|
||||
// Don't set err if any of this fails, since it's non-critical.
|
||||
if(GetControlByID(gWindow, &id, &textField) == noErr)
|
||||
{
|
||||
SetKeyboardFocus(gWindow, textField, kControlFocusNextPart);
|
||||
}
|
||||
}
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
ShowWindow(gWindow);
|
||||
}
|
||||
|
||||
if(err == noErr)
|
||||
{
|
||||
// Set up an event handler for the window.
|
||||
EventTypeSpec handlerEvents[] =
|
||||
{
|
||||
{ kEventClassCommand, kEventCommandProcess }
|
||||
};
|
||||
|
||||
InstallWindowEventHandler(
|
||||
gWindow,
|
||||
NewEventHandlerUPP(dialogHandler),
|
||||
GetEventTypeCount (handlerEvents),
|
||||
handlerEvents,
|
||||
0,
|
||||
&gEventHandler);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLCrashLoggerMac::gatherPlatformSpecificFiles()
|
||||
{
|
||||
updateApplication("Gathering hardware information...");
|
||||
char path[MAX_PATH];
|
||||
FSRef folder;
|
||||
|
||||
if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr)
|
||||
{
|
||||
// folder is an FSRef to ~/Library/Logs/
|
||||
if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr)
|
||||
{
|
||||
struct stat dw_stat;
|
||||
std::string mBuf;
|
||||
bool isLeopard = false;
|
||||
// Try the 10.3 path first...
|
||||
std::string dw_file_name = std::string(path) + std::string("/CrashReporter/Second Life.crash.log");
|
||||
int res = stat(dw_file_name.c_str(), &dw_stat);
|
||||
|
||||
if (res)
|
||||
{
|
||||
// Try the 10.2 one next...
|
||||
dw_file_name = std::string(path) + std::string("/Second Life.crash.log");
|
||||
res = stat(dw_file_name.c_str(), &dw_stat);
|
||||
}
|
||||
|
||||
if(res)
|
||||
{
|
||||
//10.5: Like 10.3+, except it puts the crash time in the file instead of dividing it up
|
||||
//using asterisks. Get a directory listing, search for files starting with second life,
|
||||
//use the last one found.
|
||||
std::string old_file_name, current_file_name, pathname, mask;
|
||||
pathname = std::string(path) + std::string("/CrashReporter/");
|
||||
mask = "Second Life*";
|
||||
while(gDirUtilp->getNextFileInDir(pathname, mask, current_file_name, false))
|
||||
{
|
||||
old_file_name = current_file_name;
|
||||
}
|
||||
if(old_file_name != "")
|
||||
{
|
||||
dw_file_name = pathname + old_file_name;
|
||||
res=stat(dw_file_name.c_str(), &dw_stat);
|
||||
isLeopard = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!res)
|
||||
{
|
||||
std::ifstream fp(dw_file_name.c_str());
|
||||
std::stringstream str;
|
||||
if(!fp.is_open()) return;
|
||||
str << fp.rdbuf();
|
||||
mBuf = str.str();
|
||||
|
||||
if(!isLeopard)
|
||||
{
|
||||
// Crash logs consist of a number of entries, one per crash.
|
||||
// Each entry is preceeded by "**********" on a line by itself.
|
||||
// We want only the most recent (i.e. last) one.
|
||||
const char *sep = "**********";
|
||||
const char *start = mBuf.c_str();
|
||||
const char *cur = start;
|
||||
const char *temp = strstr(cur, sep);
|
||||
|
||||
while(temp != NULL)
|
||||
{
|
||||
// Skip past the marker we just found
|
||||
cur = temp + strlen(sep); /* Flawfinder: ignore */
|
||||
|
||||
// and try to find another
|
||||
temp = strstr(cur, sep);
|
||||
}
|
||||
|
||||
// If there's more than one entry in the log file, strip all but the last one.
|
||||
if(cur != start)
|
||||
{
|
||||
mBuf.erase(0, cur - start);
|
||||
}
|
||||
}
|
||||
mCrashInfo["CrashLog"] = mBuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Couldn't find any CrashReporter files..." << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::mainLoop()
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
if(err == noErr && mCrashBehavior == CRASH_BEHAVIOR_ASK)
|
||||
{
|
||||
RunAppModalLoopForWindow(gWindow);
|
||||
}
|
||||
else 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();
|
||||
}
|
||||
|
||||
if(gWindow != NULL)
|
||||
{
|
||||
DisposeWindow(gWindow);
|
||||
}
|
||||
|
||||
if(nib != NULL)
|
||||
{
|
||||
DisposeNibReference(nib);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLCrashLoggerMac::updateApplication(const std::string& message)
|
||||
{
|
||||
LLCrashLogger::updateApplication();
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::cleanup()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* @file llcrashloggermac.h
|
||||
* @brief Mac OSX crash logger definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2003-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLCRASHLOGGERMAC_H
|
||||
#define LLCRASHLOGGERMAC_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llcrashlogger.h"
|
||||
#include "llstring.h"
|
||||
|
||||
class LLCrashLoggerMac : public LLCrashLogger
|
||||
{
|
||||
public:
|
||||
LLCrashLoggerMac(void);
|
||||
~LLCrashLoggerMac(void);
|
||||
virtual bool init();
|
||||
virtual bool mainLoop();
|
||||
virtual void updateApplication(const std::string& message = LLStringUtil::null);
|
||||
virtual bool cleanup();
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* @file mac_crash_logger.cpp
|
||||
* @brief Mac OSX crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2003-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llcrashloggermac.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
//time(&gLaunchTime);
|
||||
|
||||
llinfos << "Starting Second Life Viewer Crash Reporter" << llendl;
|
||||
|
||||
LLCrashLoggerMac app;
|
||||
app.parseCommandOptions(argc, argv);
|
||||
if(!app.init())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
app.mainLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
4
indra/mac_updater/AutoUpdater.nib/classes.nib
generated
4
indra/mac_updater/AutoUpdater.nib/classes.nib
generated
@@ -1,4 +0,0 @@
|
||||
{
|
||||
IBClasses = ();
|
||||
IBVersion = 1;
|
||||
}
|
||||
14
indra/mac_updater/AutoUpdater.nib/info.nib
generated
14
indra/mac_updater/AutoUpdater.nib/info.nib
generated
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>103 138 356 240 0 0 1280 1002 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>362.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>7D24</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCarbonFramework</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<object class="NSIBObjectData">
|
||||
<string name="targetFramework">IBCarbonFramework</string>
|
||||
<object name="rootObject" class="NSCustomObject" id="1">
|
||||
<string name="customClass">NSApplication</string>
|
||||
</object>
|
||||
<array count="5" name="allObjects">
|
||||
<object class="IBCarbonWindow" id="166">
|
||||
<string name="windowRect">405 222 533 663 </string>
|
||||
<string name="title">Second Life Updater</string>
|
||||
<object name="rootControl" class="IBCarbonRootControl" id="167">
|
||||
<string name="bounds">0 0 128 441 </string>
|
||||
<array count="3" name="subviews">
|
||||
<object class="IBCarbonStaticText" id="181">
|
||||
<string name="bounds">20 20 44 421 </string>
|
||||
<ostype name="controlSignature">what</ostype>
|
||||
<string name="title">Initializing…</string>
|
||||
</object>
|
||||
<object class="IBCarbonButton" id="183">
|
||||
<string name="bounds">88 351 108 421 </string>
|
||||
<string name="title">Cancel</string>
|
||||
<ostype name="command">not!</ostype>
|
||||
<int name="buttonType">2</int>
|
||||
</object>
|
||||
<object class="IBCarbonProgressBar" id="193">
|
||||
<string name="bounds">51 19 70 422 </string>
|
||||
<ostype name="controlSignature">prog</ostype>
|
||||
<int name="initialValue">50</int>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<boolean name="isResizable">FALSE</boolean>
|
||||
<int name="carbonWindowClass">2</int>
|
||||
<int name="themeBrush">3</int>
|
||||
<int name="windowPosition">7</int>
|
||||
</object>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="181"/>
|
||||
<reference idRef="183"/>
|
||||
<reference idRef="193"/>
|
||||
</array>
|
||||
<array count="5" name="allParents">
|
||||
<reference idRef="1"/>
|
||||
<reference idRef="166"/>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="167"/>
|
||||
<reference idRef="167"/>
|
||||
</array>
|
||||
<dictionary count="2" name="nameTable">
|
||||
<string>File's Owner</string>
|
||||
<reference idRef="1"/>
|
||||
<string>Updater</string>
|
||||
<reference idRef="166"/>
|
||||
</dictionary>
|
||||
<unsigned_int name="nextObjectID">194</unsigned_int>
|
||||
</object>
|
||||
@@ -1,66 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
project(mac_updater)
|
||||
|
||||
include(00-Common)
|
||||
include(CURL)
|
||||
include(LLCommon)
|
||||
include(LLVFS)
|
||||
include(Linking)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(mac_updater_SOURCE_FILES
|
||||
mac_updater.cpp
|
||||
)
|
||||
|
||||
set(mac_updater_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
)
|
||||
|
||||
set_source_files_properties(${mac_updater_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND mac_updater_SOURCE_FILES ${mac_updater_HEADER_FILES})
|
||||
|
||||
|
||||
set(mac_updater_RESOURCE_FILES
|
||||
AutoUpdater.nib/
|
||||
)
|
||||
set_source_files_properties(
|
||||
${mac_updater_RESOURCE_FILES}
|
||||
PROPERTIES
|
||||
HEADER_FILE_ONLY TRUE
|
||||
)
|
||||
SOURCE_GROUP("Resources" FILES ${mac_updater_RESOURCE_FILES})
|
||||
list(APPEND mac_updater_SOURCE_FILES ${mac_updater_RESOURCE_FILES})
|
||||
|
||||
add_executable(mac-updater
|
||||
MACOSX_BUNDLE
|
||||
${mac_updater_SOURCE_FILES})
|
||||
|
||||
set_target_properties(mac-updater
|
||||
PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
)
|
||||
|
||||
target_link_libraries(mac-updater
|
||||
${LLVFS_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET mac-updater POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
-E
|
||||
copy_directory
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/AutoUpdater.nib
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib
|
||||
)
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>mac-updater</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.secondlife.indra.autoupdater</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string></string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -140,6 +140,7 @@ set(viewer_SOURCE_FILES
|
||||
llcompilequeue.cpp
|
||||
llconfirmationmanager.cpp
|
||||
llconsole.cpp
|
||||
llcrashlogger.cpp
|
||||
llcurrencyuimanager.cpp
|
||||
llcylinder.cpp
|
||||
lldaycyclemanager.cpp
|
||||
@@ -656,6 +657,7 @@ set(viewer_HEADER_FILES
|
||||
llcompilequeue.h
|
||||
llconfirmationmanager.h
|
||||
llconsole.h
|
||||
llcrashlogger.h
|
||||
llcurrencyuimanager.h
|
||||
llcylinder.h
|
||||
lldaycyclemanager.h
|
||||
@@ -1532,7 +1534,6 @@ if (WINDOWS)
|
||||
|
||||
if (PACKAGE)
|
||||
add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat)
|
||||
add_dependencies(package windows-updater windows-crash-logger)
|
||||
endif (PACKAGE)
|
||||
endif (WINDOWS)
|
||||
|
||||
@@ -1684,7 +1685,6 @@ if (DARWIN)
|
||||
|
||||
if (PACKAGE)
|
||||
add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME})
|
||||
add_dependencies(package mac-updater mac-crash-logger)
|
||||
|
||||
add_custom_command(
|
||||
TARGET package POST_BUILD
|
||||
|
||||
@@ -2199,7 +2199,7 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string />
|
||||
<string>http://crash.singularityviewer.org/submit.php</string>>
|
||||
</map>
|
||||
<key>AFKTimeout</key>
|
||||
<map>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
#include "llvocache.h"
|
||||
#include "llvopartgroup.h"
|
||||
#include "llfloaterteleporthistory.h"
|
||||
|
||||
#include "llcrashlogger.h"
|
||||
#include "llweb.h"
|
||||
#include "llsecondlifeurls.h"
|
||||
|
||||
@@ -640,6 +640,10 @@ bool LLAppViewer::init()
|
||||
initMaxHeapSize() ;
|
||||
|
||||
LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")) ;
|
||||
// Check if we have a crash report to send
|
||||
LLCrashLogger crashLogger;
|
||||
crashLogger.checkCrashDump();
|
||||
|
||||
// write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
|
||||
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
|
||||
mDumpPath = logdir;
|
||||
|
||||
@@ -23,13 +23,9 @@
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llcrashlogger.h"
|
||||
#include "llcrashlock.h"
|
||||
#include "linden_common.h"
|
||||
#include "llstring.h"
|
||||
#include "indra_constants.h" // CRASH_BEHAVIOR_...
|
||||
@@ -46,12 +42,6 @@
|
||||
#include "llproxy.h"
|
||||
#include "aistatemachine.h"
|
||||
|
||||
LLPumpIO* gServicePump;
|
||||
BOOL gBreak = false;
|
||||
BOOL gSent = false;
|
||||
|
||||
extern void startEngineThread(void);
|
||||
|
||||
class AIHTTPTimeoutPolicy;
|
||||
extern AIHTTPTimeoutPolicy crashLoggerResponder_timeout;
|
||||
|
||||
@@ -64,13 +54,12 @@ public:
|
||||
|
||||
virtual void error(U32 status, const std::string& reason)
|
||||
{
|
||||
gBreak = true;
|
||||
llwarns << "Crash report sending failed: " << reason << llendl;
|
||||
}
|
||||
|
||||
virtual void result(const LLSD& content)
|
||||
{
|
||||
gBreak = true;
|
||||
gSent = true;
|
||||
llinfos << "Crash report successfully sent" << llendl;
|
||||
}
|
||||
|
||||
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const
|
||||
@@ -88,7 +77,6 @@ LLCrashLogger::LLCrashLogger() :
|
||||
mCrashBehavior(CRASH_BEHAVIOR_ALWAYS_SEND),
|
||||
mCrashInPreviousExec(false),
|
||||
mCrashSettings("CrashSettings"),
|
||||
mSentCrashLogs(false),
|
||||
mCrashHost("")
|
||||
{
|
||||
}
|
||||
@@ -250,32 +238,6 @@ 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";
|
||||
}
|
||||
|
||||
// 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";
|
||||
|
||||
mCrashInfo["DebugLog"] = mDebugLog;
|
||||
mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"stats.log");
|
||||
|
||||
@@ -354,80 +316,15 @@ LLSD LLCrashLogger::constructPostData()
|
||||
return mCrashInfo;
|
||||
}
|
||||
|
||||
// Singu Note, defiend in indra_constants.h # const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml";
|
||||
|
||||
S32 LLCrashLogger::loadCrashBehaviorSetting()
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
// Next check app_settings (in the SL program dir)
|
||||
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, CRASH_SETTINGS_FILE);
|
||||
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;
|
||||
}
|
||||
|
||||
bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout)
|
||||
{
|
||||
gBreak = false;
|
||||
for(int i = 0; i < retries; ++i)
|
||||
{
|
||||
updateApplication(llformat("%s, try %d...", msg.c_str(), i+1));
|
||||
LLHTTPClient::post(host, data, new LLCrashLoggerResponder());
|
||||
while(!gBreak)
|
||||
{
|
||||
updateApplication(); // No new message, just pump the IO
|
||||
}
|
||||
if(gSent)
|
||||
{
|
||||
return gSent;
|
||||
}
|
||||
}
|
||||
return gSent;
|
||||
}
|
||||
|
||||
bool LLCrashLogger::sendCrashLog(std::string dump_dir)
|
||||
{
|
||||
gDirUtilp->setDumpDir( dump_dir );
|
||||
|
||||
std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
|
||||
"SecondLifeCrashReport");
|
||||
"SingularityCrashReport");
|
||||
std::string report_file = dump_path + ".log";
|
||||
|
||||
|
||||
gatherFiles();
|
||||
|
||||
LLSD post_data;
|
||||
@@ -438,176 +335,30 @@ bool LLCrashLogger::sendCrashLog(std::string dump_dir)
|
||||
std::ofstream out_file(report_file.c_str());
|
||||
LLSDSerialize::toPrettyXML(post_data, out_file);
|
||||
out_file.close();
|
||||
|
||||
bool sent = false;
|
||||
|
||||
//*TODO: Translate
|
||||
if(mCrashHost != "")
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
mSentCrashLogs = sent;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
bool LLCrashLogger::sendCrashLogs()
|
||||
{
|
||||
LLHTTPClient::post(mCrashHost, post_data, new LLCrashLoggerResponder());
|
||||
|
||||
//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") )
|
||||
{
|
||||
rec["pid"]=opts["pid"];
|
||||
rec["dumpdir"]=opts["dumpdir"];
|
||||
rec["procname"]=opts["procname"];
|
||||
#if LL_WINDOWS
|
||||
locks.append(rec);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (locks.isArray())
|
||||
{
|
||||
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");
|
||||
|
||||
mKeyMaster.cleanupProcess((*lock)["dumpdir"].asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Discarding corrupted entry from lock table." << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !LL_WINDOWS
|
||||
if (rec)
|
||||
{
|
||||
newlocks.append(rec);
|
||||
}
|
||||
#endif
|
||||
|
||||
mKeyMaster.putProcessList(newlocks);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLCrashLogger::updateApplication(const std::string& message)
|
||||
{
|
||||
/* Sing TODO
|
||||
gServicePump->pump();
|
||||
gServicePump->callback();
|
||||
*/
|
||||
if (!message.empty()) llinfos << message << llendl;
|
||||
}
|
||||
|
||||
bool LLCrashLogger::init()
|
||||
{
|
||||
LLCurl::initCurl();
|
||||
AIEngine::setMaxCount(100);
|
||||
|
||||
// We assume that all the logs we're looking for reside on the current drive
|
||||
gDirUtilp->initAppDirs("SecondLife");
|
||||
|
||||
LLError::initForApplication(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
|
||||
|
||||
// Default to the product name "Second Life" (this is overridden by the -name argument)
|
||||
mProductName = "Second Life";
|
||||
|
||||
// Handle locking
|
||||
bool locked = mKeyMaster.requestMaster(); //Request maser locking file. wait time is defaulted to 300S
|
||||
|
||||
while (!locked && mKeyMaster.isWaiting())
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
locked = mKeyMaster.checkMaster();
|
||||
}
|
||||
|
||||
if (!locked)
|
||||
{
|
||||
llwarns << "Unable to get master lock. Another crash reporter may be hung." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rename current log file to ".old"
|
||||
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old");
|
||||
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log");
|
||||
|
||||
#if LL_WINDOWS
|
||||
LLAPRFile::remove(old_log_file);
|
||||
#endif
|
||||
|
||||
LLFile::rename(log_file.c_str(), old_log_file.c_str());
|
||||
|
||||
// Set the log file to crashreport.log
|
||||
LLError::logToFile(log_file);
|
||||
|
||||
mCrashSettings.declareS32("CrashSubmitBehavior", CRASH_BEHAVIOR_ALWAYS_SEND,
|
||||
"Controls behavior when viewer crashes "
|
||||
"(0 = ask before sending crash report, "
|
||||
"1 = always send crash report, "
|
||||
"2 = never send crash report)");
|
||||
|
||||
llinfos << "Loading crash behavior setting" << llendl;
|
||||
mCrashBehavior = loadCrashBehaviorSetting();
|
||||
|
||||
// If user doesn't want to send, bail out
|
||||
if (mCrashBehavior == CRASH_BEHAVIOR_NEVER_SEND)
|
||||
{
|
||||
llinfos << "Crash behavior is never_send, quitting" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
AICurlInterface::startCurlThread(&mCrashSettings);
|
||||
startEngineThread();
|
||||
/* Singu Note: not needed for AICurl
|
||||
gServicePump = new LLPumpIO(gAPRPoolp);
|
||||
gServicePump->prime(gAPRPoolp);
|
||||
LLHTTPClient::setPump(*gServicePump);
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
// For cleanup code common to all platforms.
|
||||
void LLCrashLogger::commonCleanup()
|
||||
|
||||
void LLCrashLogger::updateApplication(const std::string& message)
|
||||
{
|
||||
LLProxy::cleanupClass();
|
||||
if (!message.empty()) llinfos << message << llendl;
|
||||
}
|
||||
|
||||
|
||||
void LLCrashLogger::checkCrashDump()
|
||||
{
|
||||
mCrashHost = gSavedSettings.getString("CrashHostUrl");
|
||||
std::string dumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "") + "singularity-debug";
|
||||
if (gDirUtilp->fileExists(dumpDir))
|
||||
{
|
||||
sendCrashLog(dumpDir);
|
||||
gDirUtilp->deleteDirAndContents(dumpDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "No crash dump found frome previous run, not sending report" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,8 @@
|
||||
#include "llapp.h"
|
||||
#include "llsd.h"
|
||||
#include "llcontrol.h"
|
||||
#include "llcrashlock.h"
|
||||
|
||||
class LLCrashLogger : public LLApp
|
||||
class LLCrashLogger
|
||||
{
|
||||
public:
|
||||
LLCrashLogger();
|
||||
@@ -48,17 +47,12 @@ public:
|
||||
virtual void gatherPlatformSpecificFiles() {}
|
||||
bool saveCrashBehaviorSetting(S32 crash_behavior);
|
||||
bool sendCrashLog(std::string dump_dir);
|
||||
bool sendCrashLogs();
|
||||
LLSD constructPostData();
|
||||
virtual void updateApplication(const std::string& message = LLStringUtil::null);
|
||||
virtual bool init();
|
||||
virtual bool mainLoop() = 0;
|
||||
virtual bool cleanup() = 0;
|
||||
void commonCleanup();
|
||||
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
|
||||
S32 getCrashBehavior() { return mCrashBehavior; }
|
||||
bool runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout);
|
||||
bool readMinidump(std::string minidump_path);
|
||||
void checkCrashDump();
|
||||
|
||||
protected:
|
||||
S32 mCrashBehavior;
|
||||
@@ -69,10 +63,7 @@ protected:
|
||||
std::string mProductName;
|
||||
LLSD mCrashInfo;
|
||||
std::string mCrashHost;
|
||||
std::string mAltCrashHost;
|
||||
LLSD mDebugLog;
|
||||
bool mSentCrashLogs;
|
||||
LLCrashLock mKeyMaster;
|
||||
};
|
||||
|
||||
#endif //LLCRASHLOGGER_H
|
||||
@@ -339,10 +339,6 @@ class WindowsManifest(ViewerManifest):
|
||||
self.path(path_pair[1])
|
||||
self.end_prefix()
|
||||
|
||||
# pull in the crash logger and updater from other projects
|
||||
self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'], dst="win_crash_logger.exe")
|
||||
self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'], dst="updater.exe")
|
||||
|
||||
|
||||
def nsi_file_commands(self, install=True):
|
||||
def wpath(path):
|
||||
@@ -545,18 +541,10 @@ class DarwinManifest(ViewerManifest):
|
||||
print "Skipping libfmodex.dylib - not found"
|
||||
pass
|
||||
|
||||
# our apps
|
||||
try:
|
||||
self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app")
|
||||
self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app")
|
||||
except:
|
||||
pass
|
||||
|
||||
# plugin launcher
|
||||
self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app")
|
||||
|
||||
# dependencies on shared libs
|
||||
mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources")
|
||||
slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources")
|
||||
for libfile in ("libllcommon.dylib",
|
||||
"libapr-1.0.dylib",
|
||||
@@ -717,10 +705,8 @@ class LinuxManifest(ViewerManifest):
|
||||
|
||||
if self.buildtype().lower()=='release':
|
||||
self.path("secondlife-stripped","bin/"+self.binary_name())
|
||||
self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin")
|
||||
else:
|
||||
self.path("secondlife-bin","bin/"+self.binary_name())
|
||||
self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin")
|
||||
|
||||
self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin")
|
||||
if self.prefix("res-sdl"):
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
project(win_crash_logger)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLCrashLogger)
|
||||
include(LLMath)
|
||||
include(LLMessage)
|
||||
include(LLVFS)
|
||||
include(LLWindow)
|
||||
include(LLXML)
|
||||
include(Linking)
|
||||
include(LLSharedLibs)
|
||||
include(GoogleBreakpad)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLCRASHLOGGER_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLWINDOW_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${BREAKPAD_INCLUDE_DIRECTORIES}
|
||||
)
|
||||
include_directories(SYSTEM
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
${LLXML_SYSTEM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(win_crash_logger_SOURCE_FILES
|
||||
win_crash_logger.cpp
|
||||
llcrashloggerwindows.cpp
|
||||
)
|
||||
|
||||
set(win_crash_logger_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llcrashloggerwindows.h
|
||||
resource.h
|
||||
StdAfx.h
|
||||
win_crash_logger.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${win_crash_logger_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
set(win_crash_logger_RESOURCE_FILES
|
||||
ll_icon.ico
|
||||
)
|
||||
|
||||
set_source_files_properties(${win_crash_logger_RESOURCE_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
set(win_crash_logger_RESOURCE_FILES
|
||||
win_crash_logger.rc
|
||||
${win_crash_logger_RESOURCE_FILES}
|
||||
)
|
||||
|
||||
SOURCE_GROUP("Resource Files" FILES ${win_crash_logger_RESOURCE_FILES})
|
||||
|
||||
list(APPEND
|
||||
win_crash_logger_SOURCE_FILES
|
||||
${win_crash_logger_HEADER_FILES}
|
||||
${win_crash_logger_RESOURCE_FILES}
|
||||
)
|
||||
|
||||
# find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR})
|
||||
|
||||
add_executable(windows-crash-logger WIN32 ${win_crash_logger_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(windows-crash-logger
|
||||
${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}
|
||||
${LLCRASHLOGGER_LIBRARIES}
|
||||
${LLWINDOW_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLXML_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${WINDOWS_LIBRARIES}
|
||||
# ${DXGUID_LIBRARY}
|
||||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
user32
|
||||
gdi32
|
||||
ole32
|
||||
oleaut32
|
||||
wininet
|
||||
Wldap32
|
||||
)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(windows-crash-logger
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
|
||||
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
# Singu Note: not used by our build
|
||||
# ll_deploy_sharedlibs_command(windows-crash-logger)
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* @file StdAfx.cpp
|
||||
* @brief windows crash logger source file for includes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// win_crash_logger.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* @file StdAfx.h
|
||||
* @brief standard system includes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
||||
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
|
||||
// C RunTime Header Files
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
|
||||
// Local Header Files
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,548 +0,0 @@
|
||||
/**
|
||||
* @file llcrashloggerwindows.cpp
|
||||
* @brief Windows crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "resource.h"
|
||||
#include "llcrashloggerwindows.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "boost/tokenizer.hpp"
|
||||
|
||||
#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME
|
||||
#include "llerror.h"
|
||||
#include "llfile.h"
|
||||
#include "lltimer.h"
|
||||
#include "llstring.h"
|
||||
#include "lldxhardware.h"
|
||||
#include "lldir.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
#include <client/windows/crash_generation/crash_generation_server.h>
|
||||
#include <client/windows/crash_generation/client_info.h>
|
||||
|
||||
#define MAX_LOADSTRING 100
|
||||
#define MAX_STRING 2048
|
||||
const char* const SETTINGS_FILE_HEADER = "version";
|
||||
const S32 SETTINGS_FILE_VERSION = 101;
|
||||
|
||||
// Windows Message Handlers
|
||||
|
||||
// Global Variables:
|
||||
HINSTANCE hInst= NULL; // current instance
|
||||
TCHAR szTitle[MAX_LOADSTRING]; /* Flawfinder: ignore */ // The title bar text
|
||||
TCHAR szWindowClass[MAX_LOADSTRING]; /* Flawfinder: ignore */ // The title bar text
|
||||
|
||||
std::string gProductName;
|
||||
HWND gHwndReport = NULL; // Send/Don't Send dialog
|
||||
HWND gHwndProgress = NULL; // Progress window
|
||||
HCURSOR gCursorArrow = NULL;
|
||||
HCURSOR gCursorWait = NULL;
|
||||
BOOL gFirstDialog = TRUE; // Are we currently handling the Send/Don't Send dialog?
|
||||
std::stringstream gDXInfo;
|
||||
bool gSendLogs = false;
|
||||
|
||||
LLCrashLoggerWindows* LLCrashLoggerWindows::sInstance = NULL;
|
||||
|
||||
//Conversion from char* to wchar*
|
||||
//Replacement for ATL macros, doesn't allocate memory
|
||||
//For more info see: http://www.codeguru.com/forum/showthread.php?t=337247
|
||||
void ConvertLPCSTRToLPWSTR (const char* pCstring, WCHAR* outStr)
|
||||
{
|
||||
if (pCstring != NULL)
|
||||
{
|
||||
int nInputStrLen = strlen (pCstring);
|
||||
// Double NULL Termination
|
||||
int nOutputStrLen = MultiByteToWideChar(CP_ACP, 0, pCstring, nInputStrLen, NULL, 0) + 2;
|
||||
if (outStr)
|
||||
{
|
||||
memset (outStr, 0x00, sizeof (WCHAR)*nOutputStrLen);
|
||||
MultiByteToWideChar (CP_ACP, 0, pCstring, nInputStrLen, outStr, nInputStrLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write_debug(const char *str)
|
||||
{
|
||||
gDXInfo << str; /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
void write_debug(std::string& str)
|
||||
{
|
||||
write_debug(str.c_str());
|
||||
}
|
||||
|
||||
void show_progress(const std::string& message)
|
||||
{
|
||||
std::wstring msg = wstring_to_utf16str(utf8str_to_wstring(message));
|
||||
if (gHwndProgress)
|
||||
{
|
||||
SendDlgItemMessage(gHwndProgress, // handle to destination window
|
||||
IDC_LOG,
|
||||
WM_SETTEXT, // message to send
|
||||
FALSE, // undo option
|
||||
(LPARAM)msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void update_messages()
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void sleep_and_pump_messages( U32 seconds )
|
||||
{
|
||||
const U32 CYCLES_PER_SECOND = 10;
|
||||
U32 cycles = seconds * CYCLES_PER_SECOND;
|
||||
while( cycles-- )
|
||||
{
|
||||
update_messages();
|
||||
ms_sleep(1000 / CYCLES_PER_SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
// Include product name in the window caption.
|
||||
void LLCrashLoggerWindows::ProcessCaption(HWND hWnd)
|
||||
{
|
||||
TCHAR templateText[MAX_STRING]; /* Flawfinder: ignore */
|
||||
TCHAR header[MAX_STRING];
|
||||
std::string final;
|
||||
GetWindowText(hWnd, templateText, sizeof(templateText));
|
||||
final = llformat(ll_convert_wide_to_string(templateText, CP_ACP).c_str(), gProductName.c_str());
|
||||
ConvertLPCSTRToLPWSTR(final.c_str(), header);
|
||||
SetWindowText(hWnd, header);
|
||||
}
|
||||
|
||||
|
||||
// Include product name in the diaog item text.
|
||||
void LLCrashLoggerWindows::ProcessDlgItemText(HWND hWnd, int nIDDlgItem)
|
||||
{
|
||||
TCHAR templateText[MAX_STRING]; /* Flawfinder: ignore */
|
||||
TCHAR header[MAX_STRING];
|
||||
std::string final;
|
||||
GetDlgItemText(hWnd, nIDDlgItem, templateText, sizeof(templateText));
|
||||
final = llformat(ll_convert_wide_to_string(templateText, CP_ACP).c_str(), gProductName.c_str());
|
||||
ConvertLPCSTRToLPWSTR(final.c_str(), header);
|
||||
SetDlgItemText(hWnd, nIDDlgItem, header);
|
||||
}
|
||||
|
||||
bool handle_button_click(WORD button_id)
|
||||
{
|
||||
// Is this something other than Send or Don't Send?
|
||||
if (button_id != IDOK
|
||||
&& button_id != IDCANCEL)
|
||||
{
|
||||
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;
|
||||
|
||||
// Send the crash report if requested
|
||||
if (button_id == IDOK)
|
||||
{
|
||||
gSendLogs = TRUE;
|
||||
WCHAR wbuffer[20000];
|
||||
GetDlgItemText(gHwndReport, // handle to dialog box
|
||||
IDC_EDIT1, // control identifier
|
||||
wbuffer, // pointer to buffer for text
|
||||
20000 // maximum size of string
|
||||
);
|
||||
std::string user_text(ll_convert_wide_to_string(wbuffer, CP_ACP));
|
||||
// Activate and show the window.
|
||||
ShowWindow(gHwndProgress, SW_SHOW);
|
||||
// Try doing this second to make the progress window go frontmost.
|
||||
ShowWindow(gHwndReport, SW_HIDE);
|
||||
((LLCrashLoggerWindows*)LLCrashLogger::instance())->setUserText(user_text);
|
||||
((LLCrashLoggerWindows*)LLCrashLogger::instance())->sendCrashLogs();
|
||||
}
|
||||
// Quit the app
|
||||
LLApp::setQuitting();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
switch( message )
|
||||
{
|
||||
case WM_CREATE:
|
||||
return 0;
|
||||
|
||||
case WM_COMMAND:
|
||||
if( gFirstDialog )
|
||||
{
|
||||
WORD button_id = LOWORD(wParam);
|
||||
bool handled = handle_button_click(button_id);
|
||||
if (handled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
// Closing the window cancels
|
||||
LLApp::setQuitting();
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
LLCrashLoggerWindows::LLCrashLoggerWindows(void)
|
||||
{
|
||||
if (LLCrashLoggerWindows::sInstance==NULL)
|
||||
{
|
||||
sInstance = this;
|
||||
}
|
||||
}
|
||||
|
||||
LLCrashLoggerWindows::~LLCrashLoggerWindows(void)
|
||||
{
|
||||
sInstance = NULL;
|
||||
}
|
||||
|
||||
bool LLCrashLoggerWindows::getMessageWithTimeout(MSG *msg, UINT to)
|
||||
{
|
||||
bool res;
|
||||
const int timerID=37;
|
||||
SetTimer(NULL, timerID, to, NULL);
|
||||
res = GetMessage(msg, NULL, 0, 0);
|
||||
KillTimer(NULL, timerID);
|
||||
if (!res)
|
||||
return false;
|
||||
if (msg->message == WM_TIMER && msg->hwnd == NULL && msg->wParam == 1)
|
||||
return false; //TIMEOUT! You could call SetLastError() or something...
|
||||
return true;
|
||||
}
|
||||
|
||||
int LLCrashLoggerWindows::processingLoop() {
|
||||
const int millisecs=1000;
|
||||
static int first_connect = 1;
|
||||
|
||||
LLSD options = getOptionData( LLApp::PRIORITY_COMMAND_LINE );
|
||||
|
||||
MSG msg;
|
||||
|
||||
bool result;
|
||||
|
||||
while (1)
|
||||
{
|
||||
result = getMessageWithTimeout(&msg, millisecs);
|
||||
if ( result )
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
if (first_connect )
|
||||
{
|
||||
if ( mClientsConnected > 0)
|
||||
{
|
||||
first_connect = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mClientsConnected == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!mKeyMaster.isProcessAlive(mPID, mProcName) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llinfos << "session ending.." << llendl;
|
||||
|
||||
llinfos << "clients connected :" << mClientsConnected << llendl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void LLCrashLoggerWindows::OnClientConnected(void* context,
|
||||
const google_breakpad::ClientInfo* client_info)
|
||||
{
|
||||
llinfos << "client start. pid = " << client_info->pid() << llendl;
|
||||
sInstance->mClientsConnected++;
|
||||
|
||||
}
|
||||
|
||||
void LLCrashLoggerWindows::OnClientExited(void* context,
|
||||
const google_breakpad::ClientInfo* client_info)
|
||||
{
|
||||
llinfos << "client end. pid = " << client_info->pid() << llendl;
|
||||
sInstance->mClientsConnected--;
|
||||
}
|
||||
|
||||
/*
|
||||
void LLCrashLoggerWindows::OnClientDumpRequest(void* context,
|
||||
const google_breakpad::ClientInfo* client_info,
|
||||
const std::wstring* file_path)
|
||||
{
|
||||
ProcessingLock lock;
|
||||
|
||||
if (!file_path)
|
||||
{
|
||||
llwarns << "dump with no file path" << llendl;
|
||||
return;
|
||||
}
|
||||
if (!client_info)
|
||||
{
|
||||
llwarns << "dump with no client info" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLCrashLoggerWindows* self = static_cast<LLCrashLoggerWindows*>(context);
|
||||
if (!self)
|
||||
{
|
||||
llwarns << "dump with no context" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD pid = client_info->pid();
|
||||
|
||||
|
||||
// Send the crash dump using a worker thread. This operation has retry
|
||||
// logic in case there is no internet connection at the time.
|
||||
DumpJobInfo* dump_job = new DumpJobInfo(pid, self, map,
|
||||
dump_location.value());
|
||||
if (!::QueueUserWorkItem(&CrashService::AsyncSendDump,
|
||||
dump_job, WT_EXECUTELONGFUNCTION)) {
|
||||
LOG(ERROR) << "could not queue job";
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool LLCrashLoggerWindows::initCrashServer()
|
||||
{
|
||||
//For Breakpad on Windows we need a full Out of Process service to get good data.
|
||||
//This routine starts up the service on a named pipe that the viewer will then
|
||||
//communicate with.
|
||||
using namespace google_breakpad;
|
||||
|
||||
LLSD options = getOptionData( LLApp::PRIORITY_COMMAND_LINE );
|
||||
std::string dump_path = options["dumpdir"].asString();
|
||||
mClientsConnected = 0;
|
||||
mPID = options["pid"].asInteger();
|
||||
mProcName = options["procname"].asString();
|
||||
|
||||
std::wostringstream ws;
|
||||
//Generate a quasi-uniq name for the named pipe. For our purposes
|
||||
//this is unique-enough with least hassle. Worst case for duplicate name
|
||||
//is a second instance of the viewer will not do crash reporting.
|
||||
ws << mCrashReportPipeStr << mPID;
|
||||
std::wstring wpipe_name = ws.str();
|
||||
|
||||
std::wstring wdump_path;
|
||||
wdump_path.assign(dump_path.begin(), dump_path.end());
|
||||
|
||||
//Pipe naming conventions: http://msdn.microsoft.com/en-us/library/aa365783%28v=vs.85%29.aspx
|
||||
mCrashHandler = new CrashGenerationServer( (WCHAR *)wpipe_name.c_str(),
|
||||
NULL,
|
||||
&LLCrashLoggerWindows::OnClientConnected, this,
|
||||
NULL, NULL, // &LLCrashLoggerWindows::OnClientDumpRequest, this,
|
||||
&LLCrashLoggerWindows::OnClientExited, this,
|
||||
NULL, NULL,
|
||||
true, &wdump_path);
|
||||
|
||||
if (!mCrashHandler) {
|
||||
//Failed to start the crash server.
|
||||
llwarns << "Failed to init crash server." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start servicing clients.
|
||||
if (!mCrashHandler->Start()) {
|
||||
llwarns << "Failed to start crash server." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLCrashLoggerWindows::init(void)
|
||||
{
|
||||
initCrashServer();
|
||||
bool ok = LLCrashLogger::init();
|
||||
if(!ok) return false;
|
||||
|
||||
/*
|
||||
mbstowcs( gProductName, mProductName.c_str(), LL_ARRAY_SIZE(gProductName) );
|
||||
gProductName[ LL_ARRY_SIZE(gProductName) - 1 ] = 0;
|
||||
swprintf(gProductName, L"Second Life");
|
||||
*/
|
||||
|
||||
llinfos << "Loading dialogs" << llendl;
|
||||
|
||||
// Initialize global strings
|
||||
LoadString(mhInst, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
|
||||
LoadString(mhInst, IDC_WIN_CRASH_LOGGER, szWindowClass, MAX_LOADSTRING);
|
||||
|
||||
gCursorArrow = LoadCursor(NULL, IDC_ARROW);
|
||||
gCursorWait = LoadCursor(NULL, IDC_WAIT);
|
||||
|
||||
// Register a window class that will be used by our dialogs
|
||||
WNDCLASS wndclass;
|
||||
wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndclass.lpfnWndProc = WndProc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = DLGWINDOWEXTRA; // Required, since this is used for dialogs!
|
||||
wndclass.hInstance = mhInst;
|
||||
wndclass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE( IDI_WIN_CRASH_LOGGER ) );
|
||||
wndclass.hCursor = gCursorArrow;
|
||||
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = szWindowClass;
|
||||
RegisterClass( &wndclass );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLCrashLoggerWindows::gatherPlatformSpecificFiles()
|
||||
{
|
||||
updateApplication("Gathering hardware information. App may appear frozen.");
|
||||
// DX hardware probe blocks, so we can't cancel during it
|
||||
//Generate our dx_info.log file
|
||||
SetCursor(gCursorWait);
|
||||
// At this point we're responsive enough the user could click the close button
|
||||
SetCursor(gCursorArrow);
|
||||
//mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); //Not initialized.
|
||||
}
|
||||
|
||||
bool LLCrashLoggerWindows::mainLoop()
|
||||
{
|
||||
llinfos << "CrashSubmitBehavior is " << mCrashBehavior << llendl;
|
||||
// Note: parent hwnd is 0 (the desktop). No dlg proc. See Petzold (5th ed) HexCalc example, Chapter 11, p529
|
||||
// win_crash_logger.rc has been edited by hand.
|
||||
// Dialogs defined with CLASS "WIN_CRASH_LOGGER" (must be same as szWindowClass)
|
||||
gProductName = mProductName;
|
||||
gHwndProgress = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROGRESS), 0, NULL);
|
||||
ProcessCaption(gHwndProgress);
|
||||
ShowWindow(gHwndProgress, SW_HIDE );
|
||||
|
||||
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
|
||||
{
|
||||
llinfos << "Showing crash report submit progress window." << llendl;
|
||||
ShowWindow(gHwndProgress, SW_SHOW );
|
||||
sendCrashLogs();
|
||||
}
|
||||
else if (mCrashBehavior == CRASH_BEHAVIOR_ASK)
|
||||
{
|
||||
gHwndReport = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PREVREPORTBOX), 0, NULL);
|
||||
// Ignore result
|
||||
(void) SendDlgItemMessage(gHwndReport, IDC_CHECK_AUTO, BM_SETCHECK, 0, 0);
|
||||
// Include the product name in the caption and various dialog items.
|
||||
ProcessCaption(gHwndReport);
|
||||
ProcessDlgItemText(gHwndReport, IDC_STATIC_MSG);
|
||||
|
||||
// Update the header to include whether or not we crashed on the last run.
|
||||
std::string headerStr;
|
||||
TCHAR header[MAX_STRING];
|
||||
if (mCrashInPreviousExec)
|
||||
{
|
||||
headerStr = llformat("%s appears to have crashed or frozen the last time it ran.", mProductName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
headerStr = llformat("%s appears to have crashed.", mProductName.c_str());
|
||||
}
|
||||
ConvertLPCSTRToLPWSTR(headerStr.c_str(), header);
|
||||
SetDlgItemText(gHwndReport, IDC_STATIC_HEADER, header);
|
||||
ShowWindow(gHwndReport, SW_SHOW );
|
||||
|
||||
MSG msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
while (!LLApp::isQuitting() && GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return msg.wParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Unknown crash behavior " << mCrashBehavior << llendl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LLCrashLoggerWindows::updateApplication(const std::string& message)
|
||||
{
|
||||
LLCrashLogger::updateApplication(message);
|
||||
if(!message.empty()) show_progress(message);
|
||||
update_messages();
|
||||
}
|
||||
|
||||
bool LLCrashLoggerWindows::cleanup()
|
||||
{
|
||||
if(gSendLogs)
|
||||
{
|
||||
if(mSentCrashLogs) show_progress("Done");
|
||||
else show_progress("Could not connect to servers, logs not sent");
|
||||
sleep_and_pump_messages(3);
|
||||
}
|
||||
PostQuitMessage(0);
|
||||
commonCleanup();
|
||||
mKeyMaster.releaseMaster();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* @file llcrashloggerwindows.h
|
||||
* @brief Windows crash logger definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLCRASHLOGGERWINDOWS_H
|
||||
#define LLCRASHLOGGERWINDOWS_H
|
||||
|
||||
#include "llcrashlogger.h"
|
||||
#include "windows.h"
|
||||
#include "llstring.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
namespace google_breakpad {
|
||||
class CrashGenerationServer;
|
||||
class ClientInfo;
|
||||
}
|
||||
|
||||
class LLCrashLoggerWindows : public LLCrashLogger
|
||||
{
|
||||
public:
|
||||
LLCrashLoggerWindows(void);
|
||||
~LLCrashLoggerWindows(void);
|
||||
static LLCrashLoggerWindows* sInstance;
|
||||
|
||||
virtual bool init();
|
||||
virtual bool mainLoop();
|
||||
virtual void updateApplication(const std::string& message = LLStringUtil::null);
|
||||
virtual bool cleanup();
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
void setHandle(HINSTANCE hInst) { mhInst = hInst; }
|
||||
int clients_connected() const {
|
||||
return mClientsConnected;
|
||||
}
|
||||
bool getMessageWithTimeout(MSG *msg, UINT to);
|
||||
|
||||
// Starts the processing loop. This function does not return unless the
|
||||
// user is logging off or the user closes the crash service window. The
|
||||
// return value is a good number to pass in ExitProcess().
|
||||
int processingLoop();
|
||||
private:
|
||||
void ProcessDlgItemText(HWND hWnd, int nIDDlgItem);
|
||||
void ProcessCaption(HWND hWnd);
|
||||
bool initCrashServer();
|
||||
google_breakpad::CrashGenerationServer* mCrashHandler;
|
||||
static void OnClientConnected(void* context,
|
||||
const google_breakpad::ClientInfo* client_info);
|
||||
|
||||
/*static void OnClientDumpRequest(
|
||||
void* context,
|
||||
const google_breakpad::ClientInfo* client_info,
|
||||
const std::wstring* file_path);*/
|
||||
|
||||
static void OnClientExited(void* context,
|
||||
const google_breakpad::ClientInfo* client_info);
|
||||
int mClientsConnected;
|
||||
int mPID;
|
||||
std::string mProcName;
|
||||
|
||||
HINSTANCE mhInst;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* @file resource.h
|
||||
* @brief Windows crash logger windows resources
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by win_crash_logger.rc
|
||||
//
|
||||
#define IDC_MYICON 2
|
||||
#define IDD_REPORT 9
|
||||
#define IDD_WIN_CRASH_LOGGER_DIALOG 102
|
||||
#define IDD_ABOUTBOX 103
|
||||
#define IDS_APP_TITLE 103
|
||||
#define IDM_ABOUT 104
|
||||
#define IDM_EXIT 105
|
||||
#define IDS_HELLO 106
|
||||
#define IDI_WIN_CRASH_LOGGER 107
|
||||
#define IDI_SMALL 108
|
||||
#define IDC_WIN_CRASH_LOGGER 109
|
||||
#define IDR_MAINFRAME 128
|
||||
#define IDD_PROGRESS 129
|
||||
#define IDD_PREVREPORTBOX 130
|
||||
#define IDC_EDIT1 1000
|
||||
#define IDC_LOG 1004
|
||||
#define IDC_CHECK_AUTO 1006
|
||||
#define IDC_STATIC_HEADER 1007
|
||||
#define IDC_STATIC_WHATINFO 1008
|
||||
#define IDC_STATIC_MOTIVATION 1009
|
||||
#define IDC_STATIC_MSG 1010
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 131
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1011
|
||||
#define _APS_NEXT_SYMED_VALUE 110
|
||||
#endif
|
||||
#endif
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* @file win_crash_logger.cpp
|
||||
* @brief Windows crash logger implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "stdafx.h"
|
||||
#include <stdlib.h>
|
||||
#include "llcrashloggerwindows.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow)
|
||||
{
|
||||
llinfos << "Starting crash reporter." << llendl;
|
||||
LLCrashLoggerWindows app;
|
||||
app.setHandle(hInstance);
|
||||
app.parseCommandOptions(__argc, __argv);
|
||||
|
||||
LLSD options = LLApp::instance()->getOptionData(
|
||||
LLApp::PRIORITY_COMMAND_LINE);
|
||||
if (!(options.has("pid") && options.has("dumpdir")))
|
||||
{
|
||||
llwarns << "Insufficient parameters to crash report." << llendl;
|
||||
}
|
||||
if (! app.init())
|
||||
{
|
||||
llwarns << "Unable to initialize application." << llendl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
app.processingLoop();
|
||||
app.mainLoop();
|
||||
app.cleanup();
|
||||
llinfos << "Crash reporter finished normally." << llendl;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* @file win_crash_logger.h
|
||||
* @brief Windows crash logger project includes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(AFX_WIN_CRASH_LOGGER_H__79802F4B_7C37_4F63_A2BB_0768788C3A27__INCLUDED_)
|
||||
#define AFX_WIN_CRASH_LOGGER_H__79802F4B_7C37_4F63_A2BB_0768788C3A27__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
#endif // !defined(AFX_WIN_CRASH_LOGGER_H__79802F4B_7C37_4F63_A2BB_0768788C3A27__INCLUDED_)
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,188 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "resource.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_WIN_CRASH_LOGGER ICON "ll_icon.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDC_WIN_CRASH_LOGGER MENU
|
||||
BEGIN
|
||||
POPUP "&File"
|
||||
BEGIN
|
||||
MENUITEM "E&xit", IDM_EXIT
|
||||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&About ...", IDM_ABOUT
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_PROGRESS DIALOGEX 100, 100, 234, 33
|
||||
STYLE DS_SETFONT | DS_SETFOREGROUND | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "%s Crash Logger"
|
||||
CLASS "WIN_CRASH_LOGGER"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Static",IDC_LOG,7,7,220,8
|
||||
END
|
||||
|
||||
IDD_REPORT DIALOGEX 100, 100, 297, 125
|
||||
STYLE DS_SETFONT | DS_SETFOREGROUND | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "%s Crash Logger"
|
||||
CLASS "WIN_CRASH_LOGGER"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Send",IDOK,198,104,45,15,WS_GROUP
|
||||
PUSHBUTTON "Don't Send",IDCANCEL,247,104,45,15,WS_GROUP
|
||||
LTEXT "%s appears to have crashed.",IDC_STATIC_HEADER,4,4,288,14
|
||||
LTEXT "This crash reporter collects information about your computer's hardware, operating system, and some %s logs, which are used for debugging purposes only.",IDC_STATIC_WHATINFO,4,23,288,19,NOT WS_GROUP
|
||||
CONTROL "Remember this choice",IDC_CHECK_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,106,89,13
|
||||
LTEXT "Sending crash reports is the best way to help us improve the quality of %s.",IDC_STATIC_MOTIVATION,4,43,288,8
|
||||
LTEXT "If you continue to experience this problem, please try:",IDC_STATIC,4,57,251,8
|
||||
LTEXT "- Contacting support by visiting http://www.secondlife.com/support",IDC_STATIC,4,67,231,8
|
||||
END
|
||||
|
||||
IDD_PREVREPORTBOX DIALOGEX 100, 100, 232, 213
|
||||
STYLE DS_SETFONT | DS_SETFOREGROUND | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "%s Crash Logger"
|
||||
CLASS "WIN_CRASH_LOGGER"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "Send Report",IDOK,131,193,45,15,WS_GROUP
|
||||
EDITTEXT IDC_EDIT1,3,100,223,89,ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL
|
||||
PUSHBUTTON "Don't Send",IDCANCEL,181,193,45,15,WS_GROUP
|
||||
LTEXT "%s appears to have crashed or frozen the last time it ran.",IDC_STATIC_HEADER,4,4,214,8
|
||||
LTEXT "This crash reporter collects information about your computer's",IDC_STATIC,4,17,201,8
|
||||
LTEXT "hardware configuration, operating system, and some %s",IDC_STATIC_MSG,4,25,212,8
|
||||
LTEXT "logs, all of which are used for debugging purposes only.",IDC_STATIC,4,33,210,8
|
||||
LTEXT "In the space below, please briefly describe what you were doing",IDC_STATIC,3,48,208,8
|
||||
LTEXT "or trying to do just prior to the crash.",IDC_STATIC,3,56,204,8
|
||||
LTEXT "If you don't wish to send Linden Lab a crash report, press Don't Send.",IDC_STATIC,3,90,223,8
|
||||
LTEXT "This report is NOT read by customer support. If you have billing or",IDC_STATIC,3,68,208,8
|
||||
LTEXT "other questions, please go to: www.secondlife.com/support",IDC_STATIC,3,76,206,8
|
||||
CONTROL "Remember this choice",IDC_CHECK_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,193,89,13
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""resource.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_PROGRESS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 227
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 26
|
||||
END
|
||||
|
||||
IDD_REPORT, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 292
|
||||
VERTGUIDE, 4
|
||||
BOTTOMMARGIN, 119
|
||||
HORZGUIDE, 4
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_APP_TITLE "win_crash_logger"
|
||||
IDS_HELLO "Hello World!"
|
||||
IDC_WIN_CRASH_LOGGER "WIN_CRASH_LOGGER"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
project(win_updater)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(Linking)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(win_updater_SOURCE_FILES updater.cpp)
|
||||
|
||||
set(win_updater_HEADER_FILES CMakeLists.txt)
|
||||
|
||||
set_source_files_properties(${win_updater_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND win_updater_SOURCE_FILES ${win_updater_HEADER_FILES})
|
||||
|
||||
add_executable(windows-updater WIN32 ${win_updater_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(windows-updater
|
||||
wininet
|
||||
user32
|
||||
gdi32
|
||||
shell32
|
||||
)
|
||||
|
||||
set_target_properties(windows-updater
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
|
||||
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
|
||||
)
|
||||
@@ -1,522 +0,0 @@
|
||||
/**
|
||||
* @file updater.cpp
|
||||
* @brief Windows auto-updater
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
//
|
||||
// Usage: updater -url <url>
|
||||
//
|
||||
|
||||
// We use dangerous fopen, strtok, mbstowcs, sprintf
|
||||
// which generates warnings on VC2005.
|
||||
// *TODO: Switch to fopen_s, strtok_s, etc.
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
|
||||
#include <windows.h>
|
||||
#include <wininet.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
int gTotalBytesRead = 0;
|
||||
DWORD gTotalBytes = -1;
|
||||
HWND gWindow = NULL;
|
||||
WCHAR gProgress[256];
|
||||
char* gUpdateURL = NULL;
|
||||
|
||||
#if _DEBUG
|
||||
std::ofstream logfile;
|
||||
#define DEBUG(expr) logfile << expr << std::endl
|
||||
#else
|
||||
#define DEBUG(expr) /**/
|
||||
#endif
|
||||
|
||||
char* wchars_to_utf8chars(const WCHAR* in_chars)
|
||||
{
|
||||
int tlen = 0;
|
||||
const WCHAR* twc = in_chars;
|
||||
while (*twc++ != 0)
|
||||
{
|
||||
tlen++;
|
||||
}
|
||||
char* outchars = new char[tlen];
|
||||
char* res = outchars;
|
||||
for (int i=0; i<tlen; i++)
|
||||
{
|
||||
int cur_char = (int)(*in_chars++);
|
||||
if (cur_char < 0x80)
|
||||
{
|
||||
*outchars++ = (char)cur_char;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outchars++ = '?';
|
||||
}
|
||||
}
|
||||
*outchars = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
class Fetcher
|
||||
{
|
||||
public:
|
||||
Fetcher(const std::wstring& uri)
|
||||
{
|
||||
// These actions are broken out as separate methods not because it
|
||||
// makes the code clearer, but to avoid triggering AntiVir and
|
||||
// McAfee-GW-Edition virus scanners (DEV-31680).
|
||||
mInet = openInet();
|
||||
mDownload = openUrl(uri);
|
||||
}
|
||||
|
||||
~Fetcher()
|
||||
{
|
||||
DEBUG("Calling InternetCloseHandle");
|
||||
InternetCloseHandle(mDownload);
|
||||
InternetCloseHandle(mInet);
|
||||
}
|
||||
|
||||
unsigned long read(char* buffer, size_t bufflen) const;
|
||||
|
||||
DWORD getTotalBytes() const
|
||||
{
|
||||
DWORD totalBytes;
|
||||
DWORD sizeof_total_bytes = sizeof(totalBytes);
|
||||
HttpQueryInfo(mDownload, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
|
||||
&totalBytes, &sizeof_total_bytes, NULL);
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
struct InetError: public std::runtime_error
|
||||
{
|
||||
InetError(const std::string& what): std::runtime_error(what) {}
|
||||
};
|
||||
|
||||
private:
|
||||
// We test results from a number of different MS functions with different
|
||||
// return types -- but the common characteristic is that 0 (i.e. (! result))
|
||||
// means an error of some kind.
|
||||
template <typename RESULT>
|
||||
static RESULT check(const std::string& desc, RESULT result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
// success, show caller
|
||||
return result;
|
||||
}
|
||||
DWORD err = GetLastError();
|
||||
std::ostringstream out;
|
||||
out << desc << " Failed: " << err;
|
||||
DEBUG(out.str());
|
||||
throw InetError(out.str());
|
||||
}
|
||||
|
||||
HINTERNET openUrl(const std::wstring& uri) const;
|
||||
HINTERNET openInet() const;
|
||||
|
||||
HINTERNET mInet, mDownload;
|
||||
};
|
||||
|
||||
HINTERNET Fetcher::openInet() const
|
||||
{
|
||||
DEBUG("Calling InternetOpen");
|
||||
// Init wininet subsystem
|
||||
return check("InternetOpen",
|
||||
InternetOpen(L"LindenUpdater", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0));
|
||||
}
|
||||
|
||||
HINTERNET Fetcher::openUrl(const std::wstring& uri) const
|
||||
{
|
||||
DEBUG("Calling InternetOpenUrl: " << wchars_to_utf8chars(uri.c_str()));
|
||||
return check("InternetOpenUrl",
|
||||
InternetOpenUrl(mInet, uri.c_str(), NULL, 0, INTERNET_FLAG_NEED_FILE, NULL));
|
||||
}
|
||||
|
||||
unsigned long Fetcher::read(char* buffer, size_t bufflen) const
|
||||
{
|
||||
unsigned long bytes_read = 0;
|
||||
DEBUG("Calling InternetReadFile");
|
||||
check("InternetReadFile",
|
||||
InternetReadFile(mDownload, buffer, bufflen, &bytes_read));
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int WINAPI get_url_into_file(const std::wstring& uri, const std::string& path, int *cancelled)
|
||||
{
|
||||
int success = FALSE;
|
||||
*cancelled = FALSE;
|
||||
|
||||
DEBUG("Opening '" << path << "'");
|
||||
|
||||
FILE* fp = fopen(path.c_str(), "wb"); /* Flawfinder: ignore */
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
DEBUG("Failed to open '" << path << "'");
|
||||
return success;
|
||||
}
|
||||
|
||||
// Note, ctor can throw, since it uses check() function.
|
||||
Fetcher fetcher(uri);
|
||||
gTotalBytes = fetcher.getTotalBytes();
|
||||
|
||||
/*==========================================================================*|
|
||||
// nobody uses total_bytes?!? What's this doing here?
|
||||
DWORD total_bytes = 0;
|
||||
success = check("InternetQueryDataAvailable",
|
||||
InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0));
|
||||
|*==========================================================================*/
|
||||
|
||||
success = FALSE;
|
||||
while(!success && !(*cancelled))
|
||||
{
|
||||
char data[BUFSIZE]; /* Flawfinder: ignore */
|
||||
unsigned long bytes_read = fetcher.read(data, sizeof(data));
|
||||
|
||||
if (!bytes_read)
|
||||
{
|
||||
DEBUG("InternetReadFile Read " << bytes_read << " bytes.");
|
||||
}
|
||||
|
||||
DEBUG("Reading Data, bytes_read = " << bytes_read);
|
||||
|
||||
if (bytes_read == 0)
|
||||
{
|
||||
// If InternetFileRead returns TRUE AND bytes_read == 0
|
||||
// we've successfully downloaded the entire file
|
||||
wsprintf(gProgress, L"Download complete.");
|
||||
success = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// write what we've got, then continue
|
||||
fwrite(data, sizeof(char), bytes_read, fp);
|
||||
|
||||
gTotalBytesRead += int(bytes_read);
|
||||
|
||||
if (gTotalBytes != -1)
|
||||
wsprintf(gProgress, L"Downloaded: %d%%", 100 * gTotalBytesRead / gTotalBytes);
|
||||
else
|
||||
wsprintf(gProgress, L"Downloaded: %dK", gTotalBytesRead / 1024);
|
||||
|
||||
}
|
||||
|
||||
DEBUG("Calling InvalidateRect");
|
||||
|
||||
// Mark the window as needing redraw (of the whole thing)
|
||||
InvalidateRect(gWindow, NULL, TRUE);
|
||||
|
||||
// Do the redraw
|
||||
DEBUG("Calling UpdateWindow");
|
||||
UpdateWindow(gWindow);
|
||||
|
||||
DEBUG("Calling PeekMessage");
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
// bail out, user cancelled
|
||||
*cancelled = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return success;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
HDC hdc; // Drawing context
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
hdc = BeginPaint(hwnd, &ps);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(hwnd, &rect);
|
||||
DrawText(hdc, gProgress, -1, &rect,
|
||||
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
||||
|
||||
EndPaint(hwnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
// Get out of full screen
|
||||
// full_screen_mode(false);
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
#define win_class_name L"FullScreen"
|
||||
|
||||
int parse_args(int argc, char **argv)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 1; j < argc; j++)
|
||||
{
|
||||
if ((!strcmp(argv[j], "-url")) && (++j < argc))
|
||||
{
|
||||
gUpdateURL = argv[j];
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing was set, let the caller know.
|
||||
if (!gUpdateURL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
// Parse the command line.
|
||||
LPSTR cmd_line_including_exe_name = GetCommandLineA();
|
||||
|
||||
const int MAX_ARGS = 100;
|
||||
int argc = 0;
|
||||
char* argv[MAX_ARGS]; /* Flawfinder: ignore */
|
||||
|
||||
#if _DEBUG
|
||||
logfile.open("updater.log", std::ios_base::out);
|
||||
DEBUG("Parsing command arguments");
|
||||
#endif
|
||||
|
||||
char *token = NULL;
|
||||
if( cmd_line_including_exe_name[0] == '\"' )
|
||||
{
|
||||
// Exe name is enclosed in quotes
|
||||
token = strtok( cmd_line_including_exe_name, "\"" );
|
||||
argv[argc++] = token;
|
||||
token = strtok( NULL, " \t," );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exe name is not enclosed in quotes
|
||||
token = strtok( cmd_line_including_exe_name, " \t," );
|
||||
}
|
||||
|
||||
while( (token != NULL) && (argc < MAX_ARGS) )
|
||||
{
|
||||
argv[argc++] = token;
|
||||
/* Get next token: */
|
||||
if (*(token + strlen(token) + 1) == '\"') /* Flawfinder: ignore */
|
||||
{
|
||||
token = strtok( NULL, "\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
token = strtok( NULL, " \t," );
|
||||
}
|
||||
}
|
||||
|
||||
gUpdateURL = NULL;
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
// Process command line arguments
|
||||
//
|
||||
|
||||
DEBUG("Processing command arguments");
|
||||
|
||||
//
|
||||
// Parse the command line arguments
|
||||
//
|
||||
int parse_args_result = parse_args(argc, argv);
|
||||
|
||||
WNDCLASSEX wndclassex = { 0 };
|
||||
//DEVMODE dev_mode = { 0 };
|
||||
|
||||
const int WINDOW_WIDTH = 250;
|
||||
const int WINDOW_HEIGHT = 100;
|
||||
|
||||
wsprintf(gProgress, L"Connecting...");
|
||||
|
||||
/* Init the WNDCLASSEX */
|
||||
wndclassex.cbSize = sizeof(WNDCLASSEX);
|
||||
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndclassex.hInstance = hInstance;
|
||||
wndclassex.lpfnWndProc = WinProc;
|
||||
wndclassex.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
||||
wndclassex.lpszClassName = win_class_name;
|
||||
|
||||
RegisterClassEx(&wndclassex);
|
||||
|
||||
// Get the size of the screen
|
||||
//EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
|
||||
|
||||
gWindow = CreateWindowEx(NULL, win_class_name,
|
||||
L"Second Life Updater",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
WINDOW_WIDTH,
|
||||
WINDOW_HEIGHT,
|
||||
NULL, NULL, hInstance, NULL);
|
||||
|
||||
ShowWindow(gWindow, nShowCmd);
|
||||
UpdateWindow(gWindow);
|
||||
|
||||
if (parse_args_result)
|
||||
{
|
||||
MessageBox(gWindow,
|
||||
L"Usage: updater -url <url> [-name <window_title>] [-program <program_name>] [-silent]",
|
||||
L"Usage", MB_OK);
|
||||
return parse_args_result;
|
||||
}
|
||||
|
||||
// Did we get a userserver to work with?
|
||||
if (!gUpdateURL)
|
||||
{
|
||||
MessageBox(gWindow, L"Please specify the download url from the command line",
|
||||
L"Error", MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Can't feed GetTempPath into GetTempFile directly
|
||||
char temp_path[MAX_PATH]; /* Flawfinder: ignore */
|
||||
if (0 == GetTempPathA(sizeof(temp_path), temp_path))
|
||||
{
|
||||
MessageBox(gWindow, L"Problem with GetTempPath()",
|
||||
L"Error", MB_OK);
|
||||
return 1;
|
||||
}
|
||||
std::string update_exec_path(temp_path);
|
||||
update_exec_path.append("Second_Life_Updater.exe");
|
||||
|
||||
WCHAR update_uri[4096];
|
||||
mbstowcs(update_uri, gUpdateURL, sizeof(update_uri));
|
||||
|
||||
int success = 0;
|
||||
int cancelled = 0;
|
||||
|
||||
// Actually do the download
|
||||
try
|
||||
{
|
||||
DEBUG("Calling get_url_into_file");
|
||||
success = get_url_into_file(update_uri, update_exec_path, &cancelled);
|
||||
}
|
||||
catch (const Fetcher::InetError& e)
|
||||
{
|
||||
(void)e;
|
||||
success = FALSE;
|
||||
DEBUG("Caught: " << e.what());
|
||||
}
|
||||
|
||||
// WinInet can't tell us if we got a 404 or not. Therefor, we check
|
||||
// for the size of the downloaded file, and assume that our installer
|
||||
// will always be greater than 1MB.
|
||||
if (gTotalBytesRead < (1024 * 1024) && ! cancelled)
|
||||
{
|
||||
MessageBox(gWindow,
|
||||
L"The Second Life auto-update has failed.\n"
|
||||
L"The problem may be caused by other software installed \n"
|
||||
L"on your computer, such as a firewall.\n"
|
||||
L"Please visit http://secondlife.com/download/ \n"
|
||||
L"to download the latest version of Second Life.\n",
|
||||
NULL, MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cancelled)
|
||||
{
|
||||
// silently exit
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
MessageBox(gWindow,
|
||||
L"Second Life download failed.\n"
|
||||
L"Please try again later.",
|
||||
NULL, MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: Make updates silent (with /S to NSIS)
|
||||
//char params[256]; /* Flawfinder: ignore */
|
||||
//sprintf(params, "/S"); /* Flawfinder: ignore */
|
||||
//MessageBox(gWindow,
|
||||
// L"Updating Second Life.\n\nSecond Life will automatically start once the update is complete. This may take a minute...",
|
||||
// L"Download Complete",
|
||||
// MB_OK);
|
||||
|
||||
/*==========================================================================*|
|
||||
// DEV-31680: ShellExecuteA() causes McAfee-GW-Edition and AntiVir
|
||||
// scanners to flag this executable as a probable virus vector.
|
||||
// Less than or equal to 32 means failure
|
||||
if (32 >= (int) ShellExecuteA(gWindow, "open", update_exec_path.c_str(), NULL,
|
||||
"C:\\", SW_SHOWDEFAULT))
|
||||
|*==========================================================================*/
|
||||
// from http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
if (! CreateProcessA(update_exec_path.c_str(), // executable file
|
||||
NULL, // command line
|
||||
NULL, // process cannot be inherited
|
||||
NULL, // thread cannot be inherited
|
||||
FALSE, // do not inherit existing handles
|
||||
0, // process creation flags
|
||||
NULL, // inherit parent's environment
|
||||
NULL, // inherit parent's current dir
|
||||
&si, // STARTUPINFO
|
||||
&pi)) // PROCESS_INFORMATION
|
||||
{
|
||||
MessageBox(gWindow, L"Update failed. Please try again later.", NULL, MB_OK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Give installer some time to open a window
|
||||
Sleep(1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user