summaryrefslogtreecommitdiff
path: root/indra/llcommon/llprocess.h
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2012-02-07 10:53:23 -0500
committerNat Goodspeed <nat@lindenlab.com>2012-02-07 10:53:23 -0500
commitaafb03b29f5166e8978931ad8b717be32d942836 (patch)
treedb1f294e7327a876ddb91ffb3ac37423f987dd83 /indra/llcommon/llprocess.h
parentd99acd56cdc41d72a073a4419e3e51c356e675bb (diff)
Convert LLProcess implementation from platform-specific to using APR.
Include logic to engage Linden apr_procattr_autokill_set() extension: on Windows, magic CreateProcess() flag must be pushed down into apr_proc_create() level. When using an APR package without that extension, present implementation should lock (e.g.) SLVoice.exe lifespan to viewer's on Windows XP but probably won't on Windows 7: need magic flag on CreateProcess(). Using APR child-termination callback requires us to define state (e.g. LLProcess::RUNNING). Take the opportunity to present Status, capturing state and (if terminated) rc or signal number; but since most of the time all caller really wants is to log the outcome, also present status string, encapsulating logic to examine state and describe exited-with-rc vs. killed-by-signal. New Status logic may report clearer results in the case of a Windows child process killed by exception. Clarify that static LLProcess::isRunning(handle) overload is only for use when the original LLProcess object has been destroyed: really only for unit tests. We necessarily retain our original platform-specific implementations for just that one method. (Nonstatic isRunning() no longer calls static method.) Clarify log output from llprocess_test.cpp in a couple places.
Diffstat (limited to 'indra/llcommon/llprocess.h')
-rw-r--r--indra/llcommon/llprocess.h64
1 files changed, 57 insertions, 7 deletions
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index 8a842589ec..689f8aedab 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -29,6 +29,7 @@
#include "llinitparam.h"
#include "llsdparam.h"
+#include "apr_thread_proc.h"
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <iosfwd> // std::ostream
@@ -95,13 +96,52 @@ public:
static LLProcessPtr create(const LLSDOrParams& params);
virtual ~LLProcess();
- // isRunning isn't const because, if child isn't running, it clears stored
- // process ID
+ // isRunning() isn't const because, when child terminates, it sets stored
+ // Status
bool isRunning(void);
-
+
+ /**
+ * State of child process
+ */
+ enum state
+ {
+ UNSTARTED, ///< initial value, invisible to consumer
+ RUNNING, ///< child process launched
+ EXITED, ///< child process terminated voluntarily
+ KILLED ///< child process terminated involuntarily
+ };
+
+ /**
+ * Status info
+ */
+ struct Status
+ {
+ Status():
+ mState(UNSTARTED),
+ mData(0)
+ {}
+
+ state mState; ///< @see state
+ /**
+ * - for mState == EXITED: mData is exit() code
+ * - for mState == KILLED: mData is signal number (Posix)
+ * - otherwise: mData is undefined
+ */
+ int mData;
+ };
+
+ /// Status query
+ Status getStatus();
+ /// English Status string query, for logging etc.
+ std::string getStatusString();
+ /// English Status string query for previously-captured Status
+ std::string getStatusString(const Status& status);
+ /// static English Status string query
+ static std::string getStatusString(const std::string& desc, const Status& status);
+
// 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);
+ bool kill(const std::string& who="");
#if LL_WINDOWS
typedef int id; ///< as returned by getProcessID()
@@ -133,18 +173,28 @@ public:
* 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().
+ *
+ * In particular, if child termination is detected by static isRunning()
+ * rather than by nonstatic isRunning(), the LLProcess object won't be
+ * aware of the child's changed status and may encounter OS errors trying
+ * to obtain it. static isRunning() is only intended for after the
+ * launching LLProcess object has been destroyed.
*/
static handle isRunning(handle, const std::string& desc="");
private:
/// constructor is private: use create() instead
LLProcess(const LLSDOrParams& params);
- void launch(const LLSDOrParams& params);
+ void autokill();
+ // Classic-C-style APR callback
+ static void status_callback(int reason, void* data, int status);
+ // Object-oriented callback
+ void handle_status(int reason, int status);
std::string mDesc;
- id mProcessID;
- handle mProcessHandle;
+ apr_proc_t mProcess;
bool mAutokill;
+ Status mStatus;
};
/// for logging