1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
/**
* @file llprocess.h
* @brief Utility class for launching, terminating, and tracking child processes.
*
* $LicenseInfo:firstyear=2008&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_LLPROCESS_H
#define LL_LLPROCESS_H
#include "llinitparam.h"
#include "llsdparam.h"
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <iosfwd> // std::ostream
#if LL_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // HANDLE (eye roll)
#endif
class LLProcess;
/// LLProcess instances are created on the heap by static factory methods and
/// managed by ref-counted pointers.
typedef boost::shared_ptr<LLProcess> LLProcessPtr;
/**
* LLProcess 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 LL_COMMON_API LLProcess: public boost::noncopyable
{
LOG_CLASS(LLProcess);
public:
/// Param block definition
struct Params: public LLInitParam::Block<Params>
{
Params():
executable("executable"),
args("args"),
cwd("cwd"),
autokill("autokill", true)
{}
/// pathname of executable
Mandatory<std::string> executable;
/**
* zero or more additional command-line arguments. Arguments are
* passed through as exactly as we can manage, whitespace and all.
* @note On Windows we manage this by implicitly double-quoting each
* argument while assembling the command line. BUT if a given argument
* is already double-quoted, we don't double-quote it again. Try to
* avoid making use of this, though, as on Mac and Linux explicitly
* double-quoted args will be passed to the child process including
* the double quotes.
*/
Multiple<std::string> args;
/// current working directory, if need it changed
Optional<std::string> cwd;
/// implicitly kill process on destruction of LLProcess object
Optional<bool> autokill;
};
typedef LLSDParamAdapter<Params> LLSDOrParams;
/**
* Factory accepting either plain LLSD::Map or Params block.
* MAY RETURN DEFAULT-CONSTRUCTED LLProcessPtr if params invalid!
*
* Redundant with Params definition above?
*
* executable (required, string): executable pathname
* args (optional, string array): extra command-line arguments
* cwd (optional, string, dft no chdir): change to this directory before executing
* autokill (optional, bool, dft true): implicit kill() on ~LLProcess
*/
static LLProcessPtr create(const LLSDOrParams& params);
virtual ~LLProcess();
// isRunning isn't const because, if child isn't running, it clears stored
// process ID
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);
#if LL_WINDOWS
typedef int id; ///< as returned by getProcessID()
typedef HANDLE handle; ///< as returned by getProcessHandle()
#else
typedef pid_t id;
typedef pid_t handle;
#endif
/**
* Get an int-like id value. This is primarily intended for a human reader
* to differentiate processes.
*/
id getProcessID() const;
/**
* Get a "handle" of a kind that you might pass to platform-specific API
* functions to engage features not directly supported by LLProcess.
*/
handle getProcessHandle() const;
/**
* Test if a process (@c handle obtained from getProcessHandle()) is still
* running. Return same nonzero @c handle value if still running, else
* zero, so you can test it like a bool. But if you want to update a
* stored variable as a side effect, you can write code like this:
* @code
* hchild = LLProcess::isRunning(hchild);
* @endcode
* @note This method is intended as a unit-test hook, not as the first of
* a whole set of operations supported on freestanding @c handle values.
* New functionality should be added as nonstatic members operating on
* the same data as getProcessHandle().
*/
static handle isRunning(handle, const std::string& desc="");
private:
/// constructor is private: use create() instead
LLProcess(const LLSDOrParams& params);
void launch(const LLSDOrParams& params);
std::string mDesc;
id mProcessID;
handle mProcessHandle;
bool mAutokill;
};
/// for logging
LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLProcess::Params&);
#endif // LL_LLPROCESS_H
|