phoenix-firestorm/indra/llcrashlogger/llcrashlock.cpp

214 lines
5.2 KiB
C++

/**
* @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 "llapr.h" // thread-related functions
#include "llcrashlock.h"
#include "lldir.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llframetimer.h"
#include <boost/filesystem.hpp>
#include <string>
#include <iostream>
#include <stdio.h>
#if LL_WINDOWS //For windows platform.
#include <llwin32headers.h>
#include <TlHelp32.h>
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.c_str());
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.c_str());
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)
{
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
boost::filesystem::path file_path(utf8str_to_utf16str(filename));
#else
boost::filesystem::path file_path(filename);
#endif
return boost::filesystem::exists(file_path);
}
void LLCrashLock::cleanupProcess(std::string proc_dir)
{
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
boost::filesystem::path dir_path(utf8str_to_utf16str(proc_dir));
#else
boost::filesystem::path dir_path(proc_dir);
#endif
boost::filesystem::remove_all(dir_path);
}
bool LLCrashLock::putProcessList(const LLSD& proc_sd)
{
return putLockFile(mDumpTable,proc_sd);
}