diff options
Diffstat (limited to 'indra/llcrashlogger/llcrashlock.cpp')
-rw-r--r-- | indra/llcrashlogger/llcrashlock.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/indra/llcrashlogger/llcrashlock.cpp b/indra/llcrashlogger/llcrashlock.cpp new file mode 100644 index 0000000000..c3d2f944fc --- /dev/null +++ b/indra/llcrashlogger/llcrashlock.cpp @@ -0,0 +1,209 @@ +/** + * @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); +} |