From 35df5441d3e2789663532c948731aff3a1e04728 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 12:04:49 +0200 Subject: llmediaplugins first step --- linden/indra/llcommon/CMakeLists.txt | 2 + linden/indra/llcommon/llerrorcontrol.h | 1 + linden/indra/llcommon/llprocesslauncher.cpp | 346 ++++++++++++++++++++++++++++ linden/indra/llcommon/llprocesslauncher.h | 86 +++++++ 4 files changed, 435 insertions(+) create mode 100644 linden/indra/llcommon/llprocesslauncher.cpp create mode 100644 linden/indra/llcommon/llprocesslauncher.h (limited to 'linden/indra/llcommon') diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt index 3f14be6..1c12e55 100644 --- a/linden/indra/llcommon/CMakeLists.txt +++ b/linden/indra/llcommon/CMakeLists.txt @@ -42,6 +42,7 @@ set(llcommon_SOURCE_FILES llmetrics.cpp llmortician.cpp llprocessor.cpp + llprocesslauncher.cpp llqueuedthread.cpp llrand.cpp llrun.cpp @@ -136,6 +137,7 @@ set(llcommon_HEADER_FILES llnametable.h llpreprocessor.h llpriqueuemap.h + llprocesslauncher.h llprocessor.h llptrskiplist.h llptrskipmap.h diff --git a/linden/indra/llcommon/llerrorcontrol.h b/linden/indra/llcommon/llerrorcontrol.h index a55d706..fae7547 100644 --- a/linden/indra/llcommon/llerrorcontrol.h +++ b/linden/indra/llcommon/llerrorcontrol.h @@ -73,6 +73,7 @@ namespace LLError void setFunctionLevel(const std::string& function_name, LLError::ELevel); void setClassLevel(const std::string& class_name, LLError::ELevel); void setFileLevel(const std::string& file_name, LLError::ELevel); + void setTagLevel(const std::string& file_name, LLError::ELevel); void configure(const LLSD&); // the LLSD can configure all of the settings diff --git a/linden/indra/llcommon/llprocesslauncher.cpp b/linden/indra/llcommon/llprocesslauncher.cpp new file mode 100644 index 0000000..e27aaa3 --- /dev/null +++ b/linden/indra/llcommon/llprocesslauncher.cpp @@ -0,0 +1,346 @@ +/** + * @file llprocesslauncher.cpp + * @brief Utility class for launching, terminating, and tracking the state of processes. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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 "llprocesslauncher.h" + +#include +#if LL_DARWIN || LL_LINUX +// not required or present on Win32 +#include +#endif + +LLProcessLauncher::LLProcessLauncher() +{ +#if LL_WINDOWS + mProcessHandle = 0; +#else + mProcessID = 0; +#endif +} + +LLProcessLauncher::~LLProcessLauncher() +{ + kill(); +} + +void LLProcessLauncher::setExecutable(const std::string &executable) +{ + mExecutable = executable; +} + +void LLProcessLauncher::setWorkingDirectory(const std::string &dir) +{ + mWorkingDir = dir; +} + +void LLProcessLauncher::clearArguments() +{ + mLaunchArguments.clear(); +} + +void LLProcessLauncher::addArgument(const std::string &arg) +{ + mLaunchArguments.push_back(arg); +} + +void LLProcessLauncher::addArgument(const char *arg) +{ + mLaunchArguments.push_back(std::string(arg)); +} + +#if LL_WINDOWS + +int LLProcessLauncher::launch(void) +{ + // If there was already a process associated with this object, kill it. + kill(); + orphan(); + + int result = 0; + + PROCESS_INFORMATION pinfo; + STARTUPINFOA sinfo; + memset(&sinfo, 0, sizeof(sinfo)); + + std::string args = "\"" + mExecutable + "\""; + for(int i = 0; i < (int)mLaunchArguments.size(); i++) + { + args += " "; + args += mLaunchArguments[i]; + } + LL_INFOS("Plugin") << "Executable: " << mExecutable << " arguments: " << args << LL_ENDL; + + // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... + char *args2 = new char[args.size() + 1]; + strcpy(args2, args.c_str()); + + if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) ) + { + // TODO: do better than returning the OS-specific error code on failure... + result = GetLastError(); + if(result == 0) + { + // Make absolutely certain we return a non-zero value on failure. + result = -1; + } + } + else + { + // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on + // CloseHandle(pinfo.hProcess); // stops leaks - nothing else + mProcessHandle = pinfo.hProcess; + CloseHandle(pinfo.hThread); // stops leaks - nothing else + } + + delete[] args2; + + return result; +} + +bool LLProcessLauncher::isRunning(void) +{ + if(mProcessHandle != 0) + { + DWORD waitresult = WaitForSingleObject(mProcessHandle, 0); + if(waitresult == WAIT_OBJECT_0) + { + // the process has completed. + mProcessHandle = 0; + } + } + + return (mProcessHandle != 0); +} +bool LLProcessLauncher::kill(void) +{ + bool result = true; + + if(mProcessHandle != 0) + { + TerminateProcess(mProcessHandle,0); + + if(isRunning()) + { + result = false; + } + } + + return result; +} + +void LLProcessLauncher::orphan(void) +{ + // Forget about the process + mProcessHandle = 0; +} + +// static +void LLProcessLauncher::reap(void) +{ + // No actions necessary on Windows. +} + +#else // Mac and linux + +#include +#include +#include + +static std::list sZombies; + +// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise. +static bool reap_pid(pid_t pid) +{ + bool result = false; + + pid_t wait_result = ::waitpid(pid, NULL, WNOHANG); + if(wait_result == pid) + { + result = true; + } + else if(wait_result == -1) + { + if(errno == ECHILD) + { + // No such process -- this may mean we're ignoring SIGCHILD. + result = true; + } + } + + return result; +} + +int LLProcessLauncher::launch(void) +{ + // If there was already a process associated with this object, kill it. + kill(); + orphan(); + + int result = 0; + int current_wd = -1; + + // create an argv vector for the child process + const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator + + int i = 0; + + // add the executable path + fake_argv[i++] = mExecutable.c_str(); + + // and any arguments + for(int j=0; j < mLaunchArguments.size(); j++) + fake_argv[i++] = mLaunchArguments[j].c_str(); + + // terminate with a null pointer + fake_argv[i] = NULL; + + if(!mWorkingDir.empty()) + { + // save the current working directory + current_wd = ::open(".", O_RDONLY); + + // and change to the one the child will be executed in + if (::chdir(mWorkingDir.c_str())) + { + // chdir failed + } + } + + // flush all buffers before the child inherits them + ::fflush(NULL); + + pid_t id = vfork(); + if(id == 0) + { + // child process + + ::execv(mExecutable.c_str(), (char * const *)fake_argv); + + // If we reach this point, the exec failed. + // Use _exit() instead of exit() per the vfork man page. + _exit(0); + } + + // parent process + + if(current_wd >= 0) + { + // restore the previous working directory + if (::fchdir(current_wd)) + { + // chdir failed + } + ::close(current_wd); + } + + delete[] fake_argv; + + mProcessID = id; + + // At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked) + // If the process doesn't exist at this point, the exec failed. + if(!isRunning()) + { + result = -1; + } + + return result; +} + +bool LLProcessLauncher::isRunning(void) +{ + if(mProcessID != 0) + { + // Check whether the process has exited, and reap it if it has. + if(reap_pid(mProcessID)) + { + // the process has exited. + mProcessID = 0; + } + } + + return (mProcessID != 0); +} + +bool LLProcessLauncher::kill(void) +{ + bool result = true; + + if(mProcessID != 0) + { + // Try to kill the process. We'll do approximately the same thing whether the kill returns an error or not, so we ignore the result. + (void)::kill(mProcessID, SIGTERM); + + // This will have the side-effect of reaping the zombie if the process has exited. + if(isRunning()) + { + result = false; + } + } + + return result; +} + +void LLProcessLauncher::orphan(void) +{ + // Disassociate the process from this object + if(mProcessID != 0) + { + // We may still need to reap the process's zombie eventually + sZombies.push_back(mProcessID); + + mProcessID = 0; + } +} + +// static +void LLProcessLauncher::reap(void) +{ + // Attempt to real all saved process ID's. + + std::list::iterator iter = sZombies.begin(); + while(iter != sZombies.end()) + { + if(reap_pid(*iter)) + { + iter = sZombies.erase(iter); + } + else + { + iter++; + } + } +} + +#endif diff --git a/linden/indra/llcommon/llprocesslauncher.h b/linden/indra/llcommon/llprocesslauncher.h new file mode 100644 index 0000000..036732f --- /dev/null +++ b/linden/indra/llcommon/llprocesslauncher.h @@ -0,0 +1,86 @@ +/** + * @file llprocesslauncher.h + * @brief Utility class for launching, terminating, and tracking the state of processes. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-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 LL_LLPROCESSLAUNCHER_H +#define LL_LLPROCESSLAUNCHER_H + +#if LL_WINDOWS +#include +#endif + + +/* + LLProcessLauncher handles launching external processes with specified command line arguments. + It also keeps track of whether the process is still running, and can kill it if required. +*/ + +class LLProcessLauncher +{ + LOG_CLASS(LLProcessLauncher); +public: + LLProcessLauncher(); + virtual ~LLProcessLauncher(); + + void setExecutable(const std::string &executable); + void setWorkingDirectory(const std::string &dir); + + void clearArguments(); + void addArgument(const std::string &arg); + void addArgument(const char *arg); + + int launch(void); + bool isRunning(void); + + // Attempt to kill the process -- returns true if the process is no longer running when it returns. + // Note that even if this returns false, the process may exit some time after it's called. + bool kill(void); + + // Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted. + // Normally, the destructor will attempt to kill the process and wait for termination. + // This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits. + void orphan(void); + + // This needs to be called periodically on Mac/Linux to clean up zombie processes. + static void reap(void); +private: + std::string mExecutable; + std::string mWorkingDir; + std::vector mLaunchArguments; + +#if LL_WINDOWS + HANDLE mProcessHandle; +#else + pid_t mProcessID; +#endif +}; + +#endif // LL_LLPROCESSLAUNCHER_H -- cgit v1.1 From 791d4c2de7c0219392aeb625cf7940290dc1e79a Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 12:27:35 +0200 Subject: port llprimitive from SG2.0 --- linden/indra/llcommon/lllslconstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 linden/indra/llcommon/lllslconstants.h (limited to 'linden/indra/llcommon') diff --git a/linden/indra/llcommon/lllslconstants.h b/linden/indra/llcommon/lllslconstants.h old mode 100644 new mode 100755 index fc5363f..222b85d --- a/linden/indra/llcommon/lllslconstants.h +++ b/linden/indra/llcommon/lllslconstants.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2006&license=viewergpl$ * - * Copyright (c) 2006-2009, Linden Research, Inc. + * Copyright (c) 2006-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab -- cgit v1.1 From c4891694b7c8fcc469dfa057ebf397ee28fc44b1 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Thu, 17 Jun 2010 11:15:54 +0200 Subject: Robin Cornelius: fixes for building plugins on Linux 64bit --- linden/indra/llcommon/CMakeLists.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'linden/indra/llcommon') diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt index 1c12e55..ae961a3 100644 --- a/linden/indra/llcommon/CMakeLists.txt +++ b/linden/indra/llcommon/CMakeLists.txt @@ -198,3 +198,23 @@ target_link_libraries( ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ) + +if(HAVE_64_BIT) + add_library (llcommonPIC ${llcommon_SOURCE_FILES}) + add_dependencies(llcommonPIC prepare) + + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) + + target_link_libraries( + llcommonPIC + ${APRUTIL_LIBRARIES} + ${APR_LIBRARIES} + ${EXPAT_LIBRARIES} + ${ZLIB_LIBRARIES} + ) +endif(HAVE_64_BIT) + -- cgit v1.1 From b65b0ec23184885f212a78aa69edd152bdbd4588 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Thu, 21 Oct 2010 00:53:01 +0200 Subject: Add support for PluginAttachDebuggerToPlugins for linux Opens a terminal with a gdb session for newly started SLPlugin processes if PluginAttachDebuggerToPlugins is set to TRUE. --- linden/indra/llcommon/llprocesslauncher.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linden/indra/llcommon') diff --git a/linden/indra/llcommon/llprocesslauncher.h b/linden/indra/llcommon/llprocesslauncher.h index 036732f..9cdb0f6 100644 --- a/linden/indra/llcommon/llprocesslauncher.h +++ b/linden/indra/llcommon/llprocesslauncher.h @@ -80,6 +80,9 @@ private: HANDLE mProcessHandle; #else pid_t mProcessID; + +public: + pid_t getProcessID() const { return mProcessID; } #endif }; -- cgit v1.1 From 7e6a6ef92f15f4613acd6dcae9eab78f37866376 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 30 Oct 2010 20:29:37 +0200 Subject: Make LLStringUtilBase::null a constant. --- linden/indra/llcommon/llstring.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linden/indra/llcommon') diff --git a/linden/indra/llcommon/llstring.h b/linden/indra/llcommon/llstring.h index 3c6cd43..bab89b1 100644 --- a/linden/indra/llcommon/llstring.h +++ b/linden/indra/llcommon/llstring.h @@ -209,7 +209,7 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static std::basic_string null; + static std::basic_string const null; typedef std::map format_map_t; static S32 format(std::basic_string& s, const format_map_t& fmt_map); @@ -299,7 +299,7 @@ public: }; -template std::basic_string LLStringUtilBase::null; +template std::basic_string const LLStringUtilBase::null; typedef LLStringUtilBase LLStringUtil; typedef LLStringUtilBase LLWStringUtil; -- cgit v1.1