aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon
diff options
context:
space:
mode:
authorMcCabe Maxsted2010-11-02 21:32:04 -0700
committerMcCabe Maxsted2010-11-02 21:32:04 -0700
commitb5074f1a8e3306f1be9e93172d26c97ff088cea0 (patch)
treea53d5cc54a1f339b7637a9d7d8248eca42995af2 /linden/indra/llcommon
parentRevert "Fix Bug #671 (aka VWR-1603): Duckwalk is too fast" (diff)
parentUploaded the linux64 libraries created by Aleric to imprudenceviewer.org (diff)
downloadmeta-impy-b5074f1a8e3306f1be9e93172d26c97ff088cea0.zip
meta-impy-b5074f1a8e3306f1be9e93172d26c97ff088cea0.tar.gz
meta-impy-b5074f1a8e3306f1be9e93172d26c97ff088cea0.tar.bz2
meta-impy-b5074f1a8e3306f1be9e93172d26c97ff088cea0.tar.xz
Merged webkit_plugins into weekly. Huzzah! The weekly branch now has browser/media plugin support
Diffstat (limited to 'linden/indra/llcommon')
-rw-r--r--linden/indra/llcommon/CMakeLists.txt22
-rw-r--r--linden/indra/llcommon/llerrorcontrol.h1
-rwxr-xr-x[-rw-r--r--]linden/indra/llcommon/lllslconstants.h2
-rw-r--r--linden/indra/llcommon/llprocesslauncher.cpp346
-rw-r--r--linden/indra/llcommon/llprocesslauncher.h89
-rw-r--r--linden/indra/llcommon/llstring.h4
6 files changed, 461 insertions, 3 deletions
diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt
index beacce3..7d001ae 100644
--- a/linden/indra/llcommon/CMakeLists.txt
+++ b/linden/indra/llcommon/CMakeLists.txt
@@ -44,6 +44,7 @@ set(llcommon_SOURCE_FILES
44 llmetrics.cpp 44 llmetrics.cpp
45 llmortician.cpp 45 llmortician.cpp
46 llprocessor.cpp 46 llprocessor.cpp
47 llprocesslauncher.cpp
47 llqueuedthread.cpp 48 llqueuedthread.cpp
48 llrand.cpp 49 llrand.cpp
49 llrun.cpp 50 llrun.cpp
@@ -138,6 +139,7 @@ set(llcommon_HEADER_FILES
138 llnametable.h 139 llnametable.h
139 llpreprocessor.h 140 llpreprocessor.h
140 llpriqueuemap.h 141 llpriqueuemap.h
142 llprocesslauncher.h
141 llprocessor.h 143 llprocessor.h
142 llptrskiplist.h 144 llptrskiplist.h
143 llptrskipmap.h 145 llptrskipmap.h
@@ -198,3 +200,23 @@ target_link_libraries(
198 ${EXPAT_LIBRARIES} 200 ${EXPAT_LIBRARIES}
199 ${ZLIB_LIBRARIES} 201 ${ZLIB_LIBRARIES}
200 ) 202 )
203
204if(HAVE_64_BIT)
205 add_library (llcommonPIC ${llcommon_SOURCE_FILES})
206 add_dependencies(llcommonPIC prepare)
207
208 if(WINDOWS)
209 add_definitions(/FIXED:NO)
210 else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
211 add_definitions(-fPIC)
212 endif(WINDOWS)
213
214 target_link_libraries(
215 llcommonPIC
216 ${APRUTIL_LIBRARIES}
217 ${APR_LIBRARIES}
218 ${EXPAT_LIBRARIES}
219 ${ZLIB_LIBRARIES}
220 )
221endif(HAVE_64_BIT)
222
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
73 void setFunctionLevel(const std::string& function_name, LLError::ELevel); 73 void setFunctionLevel(const std::string& function_name, LLError::ELevel);
74 void setClassLevel(const std::string& class_name, LLError::ELevel); 74 void setClassLevel(const std::string& class_name, LLError::ELevel);
75 void setFileLevel(const std::string& file_name, LLError::ELevel); 75 void setFileLevel(const std::string& file_name, LLError::ELevel);
76 void setTagLevel(const std::string& file_name, LLError::ELevel);
76 77
77 void configure(const LLSD&); 78 void configure(const LLSD&);
78 // the LLSD can configure all of the settings 79 // the LLSD can configure all of the settings
diff --git a/linden/indra/llcommon/lllslconstants.h b/linden/indra/llcommon/lllslconstants.h
index a24c0a8..25a15e4 100644..100755
--- a/linden/indra/llcommon/lllslconstants.h
+++ b/linden/indra/llcommon/lllslconstants.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * $LicenseInfo:firstyear=2006&license=viewergpl$ 6 * $LicenseInfo:firstyear=2006&license=viewergpl$
7 * 7 *
8 * Copyright (c) 2006-2009, Linden Research, Inc. 8 * Copyright (c) 2006-2010, Linden Research, Inc.
9 * 9 *
10 * Second Life Viewer Source Code 10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab 11 * The source code in this file ("Source Code") is provided by Linden Lab
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 @@
1/**
2 * @file llprocesslauncher.cpp
3 * @brief Utility class for launching, terminating, and tracking the state of processes.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#include "linden_common.h"
34
35#include "llprocesslauncher.h"
36
37#include <iostream>
38#if LL_DARWIN || LL_LINUX
39// not required or present on Win32
40#include <sys/wait.h>
41#endif
42
43LLProcessLauncher::LLProcessLauncher()
44{
45#if LL_WINDOWS
46 mProcessHandle = 0;
47#else
48 mProcessID = 0;
49#endif
50}
51
52LLProcessLauncher::~LLProcessLauncher()
53{
54 kill();
55}
56
57void LLProcessLauncher::setExecutable(const std::string &executable)
58{
59 mExecutable = executable;
60}
61
62void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
63{
64 mWorkingDir = dir;
65}
66
67void LLProcessLauncher::clearArguments()
68{
69 mLaunchArguments.clear();
70}
71
72void LLProcessLauncher::addArgument(const std::string &arg)
73{
74 mLaunchArguments.push_back(arg);
75}
76
77void LLProcessLauncher::addArgument(const char *arg)
78{
79 mLaunchArguments.push_back(std::string(arg));
80}
81
82#if LL_WINDOWS
83
84int LLProcessLauncher::launch(void)
85{
86 // If there was already a process associated with this object, kill it.
87 kill();
88 orphan();
89
90 int result = 0;
91
92 PROCESS_INFORMATION pinfo;
93 STARTUPINFOA sinfo;
94 memset(&sinfo, 0, sizeof(sinfo));
95
96 std::string args = "\"" + mExecutable + "\"";
97 for(int i = 0; i < (int)mLaunchArguments.size(); i++)
98 {
99 args += " ";
100 args += mLaunchArguments[i];
101 }
102 LL_INFOS("Plugin") << "Executable: " << mExecutable << " arguments: " << args << LL_ENDL;
103
104 // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
105 char *args2 = new char[args.size() + 1];
106 strcpy(args2, args.c_str());
107
108 if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) )
109 {
110 // TODO: do better than returning the OS-specific error code on failure...
111 result = GetLastError();
112 if(result == 0)
113 {
114 // Make absolutely certain we return a non-zero value on failure.
115 result = -1;
116 }
117 }
118 else
119 {
120 // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
121 // CloseHandle(pinfo.hProcess); // stops leaks - nothing else
122 mProcessHandle = pinfo.hProcess;
123 CloseHandle(pinfo.hThread); // stops leaks - nothing else
124 }
125
126 delete[] args2;
127
128 return result;
129}
130
131bool LLProcessLauncher::isRunning(void)
132{
133 if(mProcessHandle != 0)
134 {
135 DWORD waitresult = WaitForSingleObject(mProcessHandle, 0);
136 if(waitresult == WAIT_OBJECT_0)
137 {
138 // the process has completed.
139 mProcessHandle = 0;
140 }
141 }
142
143 return (mProcessHandle != 0);
144}
145bool LLProcessLauncher::kill(void)
146{
147 bool result = true;
148
149 if(mProcessHandle != 0)
150 {
151 TerminateProcess(mProcessHandle,0);
152
153 if(isRunning())
154 {
155 result = false;
156 }
157 }
158
159 return result;
160}
161
162void LLProcessLauncher::orphan(void)
163{
164 // Forget about the process
165 mProcessHandle = 0;
166}
167
168// static
169void LLProcessLauncher::reap(void)
170{
171 // No actions necessary on Windows.
172}
173
174#else // Mac and linux
175
176#include <signal.h>
177#include <fcntl.h>
178#include <errno.h>
179
180static std::list<pid_t> sZombies;
181
182// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
183static bool reap_pid(pid_t pid)
184{
185 bool result = false;
186
187 pid_t wait_result = ::waitpid(pid, NULL, WNOHANG);
188 if(wait_result == pid)
189 {
190 result = true;
191 }
192 else if(wait_result == -1)
193 {
194 if(errno == ECHILD)
195 {
196 // No such process -- this may mean we're ignoring SIGCHILD.
197 result = true;
198 }
199 }
200
201 return result;
202}
203
204int LLProcessLauncher::launch(void)
205{
206 // If there was already a process associated with this object, kill it.
207 kill();
208 orphan();
209
210 int result = 0;
211 int current_wd = -1;
212
213 // create an argv vector for the child process
214 const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator
215
216 int i = 0;
217
218 // add the executable path
219 fake_argv[i++] = mExecutable.c_str();
220
221 // and any arguments
222 for(int j=0; j < mLaunchArguments.size(); j++)
223 fake_argv[i++] = mLaunchArguments[j].c_str();
224
225 // terminate with a null pointer
226 fake_argv[i] = NULL;
227
228 if(!mWorkingDir.empty())
229 {
230 // save the current working directory
231 current_wd = ::open(".", O_RDONLY);
232
233 // and change to the one the child will be executed in
234 if (::chdir(mWorkingDir.c_str()))
235 {
236 // chdir failed
237 }
238 }
239
240 // flush all buffers before the child inherits them
241 ::fflush(NULL);
242
243 pid_t id = vfork();
244 if(id == 0)
245 {
246 // child process
247
248 ::execv(mExecutable.c_str(), (char * const *)fake_argv);
249
250 // If we reach this point, the exec failed.
251 // Use _exit() instead of exit() per the vfork man page.
252 _exit(0);
253 }
254
255 // parent process
256
257 if(current_wd >= 0)
258 {
259 // restore the previous working directory
260 if (::fchdir(current_wd))
261 {
262 // chdir failed
263 }
264 ::close(current_wd);
265 }
266
267 delete[] fake_argv;
268
269 mProcessID = id;
270
271 // 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)
272 // If the process doesn't exist at this point, the exec failed.
273 if(!isRunning())
274 {
275 result = -1;
276 }
277
278 return result;
279}
280
281bool LLProcessLauncher::isRunning(void)
282{
283 if(mProcessID != 0)
284 {
285 // Check whether the process has exited, and reap it if it has.
286 if(reap_pid(mProcessID))
287 {
288 // the process has exited.
289 mProcessID = 0;
290 }
291 }
292
293 return (mProcessID != 0);
294}
295
296bool LLProcessLauncher::kill(void)
297{
298 bool result = true;
299
300 if(mProcessID != 0)
301 {
302 // 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.
303 (void)::kill(mProcessID, SIGTERM);
304
305 // This will have the side-effect of reaping the zombie if the process has exited.
306 if(isRunning())
307 {
308 result = false;
309 }
310 }
311
312 return result;
313}
314
315void LLProcessLauncher::orphan(void)
316{
317 // Disassociate the process from this object
318 if(mProcessID != 0)
319 {
320 // We may still need to reap the process's zombie eventually
321 sZombies.push_back(mProcessID);
322
323 mProcessID = 0;
324 }
325}
326
327// static
328void LLProcessLauncher::reap(void)
329{
330 // Attempt to real all saved process ID's.
331
332 std::list<pid_t>::iterator iter = sZombies.begin();
333 while(iter != sZombies.end())
334 {
335 if(reap_pid(*iter))
336 {
337 iter = sZombies.erase(iter);
338 }
339 else
340 {
341 iter++;
342 }
343 }
344}
345
346#endif
diff --git a/linden/indra/llcommon/llprocesslauncher.h b/linden/indra/llcommon/llprocesslauncher.h
new file mode 100644
index 0000000..9cdb0f6
--- /dev/null
+++ b/linden/indra/llcommon/llprocesslauncher.h
@@ -0,0 +1,89 @@
1/**
2 * @file llprocesslauncher.h
3 * @brief Utility class for launching, terminating, and tracking the state of processes.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#ifndef LL_LLPROCESSLAUNCHER_H
34#define LL_LLPROCESSLAUNCHER_H
35
36#if LL_WINDOWS
37#include <windows.h>
38#endif
39
40
41/*
42 LLProcessLauncher handles launching external processes with specified command line arguments.
43 It also keeps track of whether the process is still running, and can kill it if required.
44*/
45
46class LLProcessLauncher
47{
48 LOG_CLASS(LLProcessLauncher);
49public:
50 LLProcessLauncher();
51 virtual ~LLProcessLauncher();
52
53 void setExecutable(const std::string &executable);
54 void setWorkingDirectory(const std::string &dir);
55
56 void clearArguments();
57 void addArgument(const std::string &arg);
58 void addArgument(const char *arg);
59
60 int launch(void);
61 bool isRunning(void);
62
63 // Attempt to kill the process -- returns true if the process is no longer running when it returns.
64 // Note that even if this returns false, the process may exit some time after it's called.
65 bool kill(void);
66
67 // Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted.
68 // Normally, the destructor will attempt to kill the process and wait for termination.
69 // This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits.
70 void orphan(void);
71
72 // This needs to be called periodically on Mac/Linux to clean up zombie processes.
73 static void reap(void);
74private:
75 std::string mExecutable;
76 std::string mWorkingDir;
77 std::vector<std::string> mLaunchArguments;
78
79#if LL_WINDOWS
80 HANDLE mProcessHandle;
81#else
82 pid_t mProcessID;
83
84public:
85 pid_t getProcessID() const { return mProcessID; }
86#endif
87};
88
89#endif // LL_LLPROCESSLAUNCHER_H
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:
209 ///////////////////////////////////////////////////////////////////////////////////////// 209 /////////////////////////////////////////////////////////////////////////////////////////
210 // Static Utility functions that operate on std::strings 210 // Static Utility functions that operate on std::strings
211 211
212 static std::basic_string<T> null; 212 static std::basic_string<T> const null;
213 213
214 typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; 214 typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
215 static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map); 215 static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
@@ -299,7 +299,7 @@ public:
299 299
300}; 300};
301 301
302template<class T> std::basic_string<T> LLStringUtilBase<T>::null; 302template<class T> std::basic_string<T> const LLStringUtilBase<T>::null;
303 303
304typedef LLStringUtilBase<char> LLStringUtil; 304typedef LLStringUtilBase<char> LLStringUtil;
305typedef LLStringUtilBase<llwchar> LLWStringUtil; 305typedef LLStringUtilBase<llwchar> LLWStringUtil;