]> git.saurik.com Git - wxWidgets.git/commitdiff
Added flags argument to wxKill and wxProcess::Kill to allow it to
authorJulian Smart <julian@anthemion.co.uk>
Sun, 5 Dec 2004 12:53:25 +0000 (12:53 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Sun, 5 Dec 2004 12:53:25 +0000 (12:53 +0000)
kill child processes.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30855 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

12 files changed:
docs/changes.txt
docs/latex/wx/function.tex
docs/latex/wx/process.tex
include/wx/process.h
include/wx/utils.h
src/common/process.cpp
src/mac/carbon/utils.cpp
src/mac/classic/utils.cpp
src/msw/utils.cpp
src/os2/utils.cpp
src/palmos/utils.cpp
src/unix/utilsunx.cpp

index a25f4c9b505a83073d1275342029d9537115cd9a..857f4e632c0910d3e1ec39bcd30e8bb0bcf2c08c 100644 (file)
@@ -23,6 +23,7 @@ All:
 - use wxStream::GetLength() instead of deprecated GetSize()
 - wxGetOsDescription() is now more precise (Olly Betts)
 - XRC supports system fonts and colours (Ray Gilbert)
+- Added flags argument to wxKill/wxProcess::Kill to kill child processes.
 
 All (GUI):
 
index d55c16bb7c61dacda77f1aa5968de12283a4befc..3fce56f13e8af1a681ea5395199e6018dd989831 100644 (file)
@@ -577,9 +577,9 @@ happening, i.e. with this flag the child process window will be shown normally.
 
 Under Unix the flag {\tt wxEXEC\_MAKE\_GROUP\_LEADER} may be used to ensure
 that the new process is a group leader (this will create a new session if
-needed). Calling \helpref{wxKill}{wxkill} with the argument of -pid where pid
-is the process ID of the new process will kill this process as well as all of
-its children (except those which have started their own session).
+needed). Calling \helpref{wxKill}{wxkill} passing wxKILL\_CHILDREN will
+will kill this process as well as all of its children (except those which have
+started their own session).
 
 Finally, you may use the third overloaded version of this function to execute
 a process (always synchronously) and capture its output in the array
@@ -629,7 +629,7 @@ application. See \helpref{wxCloseEvent}{wxcloseevent} and \helpref{wxApp}{wxapp}
 
 \membersection{::wxKill}\label{wxkill}
 
-\func{int}{wxKill}{\param{long}{ pid}, \param{int}{ sig = wxSIGTERM}, \param{wxKillError }{*rc = NULL}}
+\func{int}{wxKill}{\param{long}{ pid}, \param{int}{ sig = wxSIGTERM}, \param{wxKillError }{*rc = NULL}, \param{int }{flags = 0}}
 
 Equivalent to the Unix kill function: send the given signal {\it sig} to the
 process with PID {\it pid}. The valid signal values are
@@ -674,6 +674,12 @@ enum wxKillError
 };
 \end{verbatim}
 
+The {\it flags} parameter can be wxKILL\_NOCHILDREN (the default),
+or wxKILL\_CHILDREN, in which case the child processes of this
+process will be killed too. Note that under Unix, for wxKILL\_CHILDREN
+to work you should have created the process by passing wxEXEC\_MAKE_GROUP\_LEADER
+to wxExecute.
+
 \wxheading{See also}
 
 \helpref{wxProcess::Kill}{wxprocesskill},\rtfsp
index d4dbeec3da2baa23d2fd6323ce33adb2361148c7..d19b33a4b087cb1418290abd7989fb8e2cf547c0 100644 (file)
@@ -155,7 +155,7 @@ Returns {\tt true} if the child process standard output stream is opened.
 
 \membersection{wxProcess::Kill}\label{wxprocesskill}
 
-\func{static wxKillError}{Kill}{\param{int}{ pid}, \param{wxSignal}{ signal = wxSIGNONE}}
+\func{static wxKillError}{Kill}{\param{int}{ pid}, \param{wxSignal}{ signal = wxSIGNONE}, \param{int }{flags = wxKILL\_NOCHILDREN}}
 
 Send the specified signal to the given process. Possible signal values are:
 
@@ -185,6 +185,11 @@ enum wxSignal
 under both Unix and Windows but all the other signals are equivalent to
 {\tt wxSIGTERM} under Windows.
 
+The {\it flags} parameter can be wxKILL\_NOCHILDREN (the default),
+or wxKILL\_CHILDREN, in which case the child processes of this
+process will be killed too. Note that under Unix, for wxKILL\_CHILDREN
+to work you should have created the process passing wxEXEC\_MAKE_GROUP\_LEADER.
+
 Returns the element of {\tt wxKillError} enum:
 
 \begin{verbatim}
index adefc2620a3db0ee8640d775bf648bab1c3a305b..fc7049d404959e59770fbabd1009dd1fc6721c82 100644 (file)
@@ -43,7 +43,7 @@ class WXDLLIMPEXP_BASE wxProcess : public wxEvtHandler
 {
 public:
     // kill the process with the given PID
-    static wxKillError Kill(int pid, wxSignal sig = wxSIGTERM);
+    static wxKillError Kill(int pid, wxSignal sig = wxSIGTERM, int flags = wxKILL_NOCHILDREN);
 
     // test if the given process exists
     static bool Exists(int pid);
index 1cc4f72a8e6c07b15e270b2e81487cb13b9a83eb..a7aba4285c40f93ed8671d8d2c4b0e5d977b9bd0 100644 (file)
@@ -156,7 +156,7 @@ WXDLLIMPEXP_BASE wxString wxDecToHex(int dec);
 // Process management
 // ----------------------------------------------------------------------------
 
-// NB: for backwars compatibility reasons the values of wxEXEC_[A]SYNC *must*
+// NB: for backwards compatibility reasons the values of wxEXEC_[A]SYNC *must*
 //     be 0 and 1, don't change!
 
 enum
@@ -171,8 +171,8 @@ enum
     // is done by default)
     wxEXEC_NOHIDE   = 2,
 
-    // under Unix, if the process is the group leader then killing -pid kills
-    // all children as well as pid
+    // under Unix, if the process is the group leader then passing wxKILL_CHILDREN to wxKill
+    // kills all children as well as pid
     wxEXEC_MAKE_GROUP_LEADER = 4
 };
 
@@ -228,6 +228,12 @@ enum wxKillError
     wxKILL_ERROR            // another, unspecified error
 };
 
+enum wxKillFlags
+{
+    wxKILL_NOCHILDREN = 0,  // don't kill children
+    wxKILL_CHILDREN = 1     // kill children
+};
+
 enum wxShutdownFlags
 {
     wxSHUTDOWN_POWEROFF,    // power off the computer
@@ -243,7 +249,8 @@ WXDLLIMPEXP_BASE bool wxShutdown(wxShutdownFlags wFlags);
 // return detailed error in rc if not NULL
 WXDLLIMPEXP_BASE int wxKill(long pid,
                        wxSignal sig = wxSIGTERM,
-                       wxKillError *rc = NULL);
+                       wxKillError *rc = NULL,
+                       int flags = wxKILL_NOCHILDREN);
 
 // Execute a command in an interactive shell window (always synchronously)
 // If no command then just the shell
index 4ef1fb157ab9e65b8b34961bb4b4a62d4da091ed..3127c762c63c33068cea2e59597efdcb2826968c 100644 (file)
@@ -142,10 +142,10 @@ bool wxProcess::IsErrorAvailable() const
 // ----------------------------------------------------------------------------
 
 /* static */
-wxKillError wxProcess::Kill(int pid, wxSignal sig)
+wxKillError wxProcess::Kill(int pid, wxSignal sig, int flags)
 {
     wxKillError rc;
-    (void)wxKill(pid, sig, &rc);
+    (void)wxKill(pid, sig, &rc, flags);
 
     return rc;
 }
index be604f9e30debdf9c1e81e07c7008cc3800d1d87..d61ce0e905f0d5a574613a21399cfbe21e653348 100644 (file)
@@ -301,7 +301,7 @@ bool wxGetUserName(wxChar *buf, int maxSize)
   return TRUE;
 }
 
-int wxKill(long pid, wxSignal sig , wxKillError *rc )
+int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
 {
     // TODO
     return 0;
index b64f77fae016318281e7df032f51286e6009a158..09ed7ad31fa29fc86827c8d5f2a9a75272853097 100644 (file)
@@ -155,7 +155,7 @@ bool wxGetUserName(wxChar *buf, int maxSize)
   return TRUE;
 }
 
-int wxKill(long pid, wxSignal sig , wxKillError *rc )
+int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
 {
     // TODO
     return 0;
index 736a8c90af397e0879e2b74f6567fed0bb5e1d16..9ff3687c46425140891a97113e69ca651970dffa 100644 (file)
@@ -94,6 +94,9 @@
     #endif
 #endif
 
+// For wxKillAllChildren
+#include <tlhelp32.h>
+
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
@@ -649,8 +652,13 @@ BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam)
     return TRUE;
 }
 
-int wxKill(long pid, wxSignal sig, wxKillError *krc)
+int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc);
+
+int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
 {
+    if (flags & wxKILL_CHILDREN)
+        wxKillAllChildren(pid, sig, krc);
+    
     // get the process handle to operate on
     HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
                                     PROCESS_TERMINATE |
@@ -805,6 +813,94 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc)
     return -1;
 }
 
+HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
+BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
+BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
+  
+static void InitToolHelp32()
+{
+    static bool s_initToolHelpDone = false;
+    
+    if (s_initToolHelpDone)
+        return;
+    
+    s_initToolHelpDone = true;
+
+    lpfCreateToolhelp32Snapshot = NULL;
+    lpfProcess32First = NULL;
+    lpfProcess32Next = NULL;
+    
+    HINSTANCE hInstLib = LoadLibraryA( "Kernel32.DLL" ) ;
+    if( hInstLib == NULL )
+        return ;
+    
+    // Get procedure addresses.
+    // We are linking to these functions of Kernel32
+    // explicitly, because otherwise a module using
+    // this code would fail to load under Windows NT,
+    // which does not have the Toolhelp32
+    // functions in the Kernel 32.
+    lpfCreateToolhelp32Snapshot=
+        (HANDLE(WINAPI *)(DWORD,DWORD))
+        GetProcAddress( hInstLib,
+        "CreateToolhelp32Snapshot" ) ;
+    
+    lpfProcess32First=
+        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+        GetProcAddress( hInstLib, "Process32First" ) ;
+
+    lpfProcess32Next=
+        (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+        GetProcAddress( hInstLib, "Process32Next" ) ;
+
+    FreeLibrary( hInstLib ) ;
+}
+
+// By John Skiff
+int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc)
+{
+    InitToolHelp32();
+    
+    if (krc)
+        *krc = wxKILL_OK;
+    
+    // If not implemented for this platform (e.g. NT 4.0), silently ignore
+    if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next)
+        return 0;
+    
+    // Take a snapshot of all processes in the system.
+    HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (hProcessSnap == INVALID_HANDLE_VALUE) {
+        if (krc)
+            *krc = wxKILL_ERROR;
+        return -1;
+    }
+    
+    //Fill in the size of the structure before using it.
+    PROCESSENTRY32 pe = {0};
+    pe.dwSize = sizeof(PROCESSENTRY32);
+    
+    // Walk the snapshot of the processes, and for each process,
+    // kill it if its parent is pid.
+    if (!lpfProcess32First(hProcessSnap, &pe)) {
+        // Can't get first process.
+        if (krc)
+            *krc = wxKILL_ERROR;
+        CloseHandle (hProcessSnap);
+        return -1;
+    }
+    
+    do {
+        if (pe.th32ParentProcessID == (DWORD) pid) {
+            if (wxKill(pe.th32ProcessID, sig, krc))
+                return -1;
+        }
+    } while (lpfProcess32Next (hProcessSnap, &pe));
+    
+    
+    return 0;
+}
+
 // Execute a program in an Interactive Shell
 bool wxShell(const wxString& command)
 {
index 80f9a04b3ca7b06ba8d9490608fdf19e3272fa85..eb3424d29df82f88dd581274a50e3bbb61761d06 100644 (file)
@@ -132,6 +132,7 @@ int wxKill(
   long                              lPid
 , wxSignal                          eSig
 , wxKillError*                      peError
+, int                               flags
 )
 {
     return((int)::DosKillProcess(0, (PID)lPid));
index 67fb7c304b4b579ea9262656efffe3e669f996f2..934ab62e50aa2f7a4ad584bb40b70e65599a8e70 100644 (file)
@@ -126,8 +126,7 @@ bool wxSetEnv(const wxString& var, const wxChar *value)
 // process management
 // ----------------------------------------------------------------------------
 
-// structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
-int wxKill(long pid, wxSignal sig, wxKillError *krc)
+int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
 {
     return 0;
 }
index 927b409122f63360b5958ea4c586084fcfe65ff1..6115ef333051e083d796849646d821714f27d87b 100644 (file)
@@ -200,9 +200,9 @@ void wxMilliSleep(unsigned long milliseconds)
 // process management
 // ----------------------------------------------------------------------------
 
-int wxKill(long pid, wxSignal sig, wxKillError *rc)
+int wxKill(long pid, wxSignal sig, wxKillError *rc, int flags)
 {
-    int err = kill((pid_t)pid, (int)sig);
+    int err = kill((pid_t) (flags & wxKILL_CHILDREN) ? -pid : pid, (int)sig);
     if ( !err )
        *rc = wxKILL_OK;
     else