Added flags argument to wxKill and wxProcess::Kill to allow it to

kill child processes.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30855 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2004-12-05 12:53:25 +00:00
parent 65c8ace850
commit e0f6b731a8
12 changed files with 134 additions and 19 deletions

View File

@@ -23,6 +23,7 @@ All:
- use wxStream::GetLength() instead of deprecated GetSize() - use wxStream::GetLength() instead of deprecated GetSize()
- wxGetOsDescription() is now more precise (Olly Betts) - wxGetOsDescription() is now more precise (Olly Betts)
- XRC supports system fonts and colours (Ray Gilbert) - XRC supports system fonts and colours (Ray Gilbert)
- Added flags argument to wxKill/wxProcess::Kill to kill child processes.
All (GUI): All (GUI):

View 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 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 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 needed). Calling \helpref{wxKill}{wxkill} passing wxKILL\_CHILDREN will
is the process ID of the new process will kill this process as well as all of will kill this process as well as all of its children (except those which have
its children (except those which have started their own session). started their own session).
Finally, you may use the third overloaded version of this function to execute Finally, you may use the third overloaded version of this function to execute
a process (always synchronously) and capture its output in the array 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} \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 Equivalent to the Unix kill function: send the given signal {\it sig} to the
process with PID {\it pid}. The valid signal values are process with PID {\it pid}. The valid signal values are
@@ -674,6 +674,12 @@ enum wxKillError
}; };
\end{verbatim} \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} \wxheading{See also}
\helpref{wxProcess::Kill}{wxprocesskill},\rtfsp \helpref{wxProcess::Kill}{wxprocesskill},\rtfsp

View File

@@ -155,7 +155,7 @@ Returns {\tt true} if the child process standard output stream is opened.
\membersection{wxProcess::Kill}\label{wxprocesskill} \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: 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 under both Unix and Windows but all the other signals are equivalent to
{\tt wxSIGTERM} under Windows. {\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: Returns the element of {\tt wxKillError} enum:
\begin{verbatim} \begin{verbatim}

View File

@@ -43,7 +43,7 @@ class WXDLLIMPEXP_BASE wxProcess : public wxEvtHandler
{ {
public: public:
// kill the process with the given PID // 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 // test if the given process exists
static bool Exists(int pid); static bool Exists(int pid);

View File

@@ -156,7 +156,7 @@ WXDLLIMPEXP_BASE wxString wxDecToHex(int dec);
// Process management // 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! // be 0 and 1, don't change!
enum enum
@@ -171,8 +171,8 @@ enum
// is done by default) // is done by default)
wxEXEC_NOHIDE = 2, wxEXEC_NOHIDE = 2,
// under Unix, if the process is the group leader then killing -pid kills // under Unix, if the process is the group leader then passing wxKILL_CHILDREN to wxKill
// all children as well as pid // kills all children as well as pid
wxEXEC_MAKE_GROUP_LEADER = 4 wxEXEC_MAKE_GROUP_LEADER = 4
}; };
@@ -228,6 +228,12 @@ enum wxKillError
wxKILL_ERROR // another, unspecified error wxKILL_ERROR // another, unspecified error
}; };
enum wxKillFlags
{
wxKILL_NOCHILDREN = 0, // don't kill children
wxKILL_CHILDREN = 1 // kill children
};
enum wxShutdownFlags enum wxShutdownFlags
{ {
wxSHUTDOWN_POWEROFF, // power off the computer wxSHUTDOWN_POWEROFF, // power off the computer
@@ -243,7 +249,8 @@ WXDLLIMPEXP_BASE bool wxShutdown(wxShutdownFlags wFlags);
// return detailed error in rc if not NULL // return detailed error in rc if not NULL
WXDLLIMPEXP_BASE int wxKill(long pid, WXDLLIMPEXP_BASE int wxKill(long pid,
wxSignal sig = wxSIGTERM, wxSignal sig = wxSIGTERM,
wxKillError *rc = NULL); wxKillError *rc = NULL,
int flags = wxKILL_NOCHILDREN);
// Execute a command in an interactive shell window (always synchronously) // Execute a command in an interactive shell window (always synchronously)
// If no command then just the shell // If no command then just the shell

View File

@@ -142,10 +142,10 @@ bool wxProcess::IsErrorAvailable() const
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/* static */ /* static */
wxKillError wxProcess::Kill(int pid, wxSignal sig) wxKillError wxProcess::Kill(int pid, wxSignal sig, int flags)
{ {
wxKillError rc; wxKillError rc;
(void)wxKill(pid, sig, &rc); (void)wxKill(pid, sig, &rc, flags);
return rc; return rc;
} }

View File

@@ -301,7 +301,7 @@ bool wxGetUserName(wxChar *buf, int maxSize)
return TRUE; return TRUE;
} }
int wxKill(long pid, wxSignal sig , wxKillError *rc ) int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
{ {
// TODO // TODO
return 0; return 0;

View File

@@ -155,7 +155,7 @@ bool wxGetUserName(wxChar *buf, int maxSize)
return TRUE; return TRUE;
} }
int wxKill(long pid, wxSignal sig , wxKillError *rc ) int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
{ {
// TODO // TODO
return 0; return 0;

View File

@@ -94,6 +94,9 @@
#endif #endif
#endif #endif
// For wxKillAllChildren
#include <tlhelp32.h>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// constants // constants
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -649,8 +652,13 @@ BOOL CALLBACK wxEnumFindByPidProc(HWND hwnd, LPARAM lParam)
return TRUE; 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 // get the process handle to operate on
HANDLE hProcess = ::OpenProcess(SYNCHRONIZE | HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
PROCESS_TERMINATE | PROCESS_TERMINATE |
@@ -805,6 +813,94 @@ int wxKill(long pid, wxSignal sig, wxKillError *krc)
return -1; 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 // Execute a program in an Interactive Shell
bool wxShell(const wxString& command) bool wxShell(const wxString& command)
{ {

View File

@@ -132,6 +132,7 @@ int wxKill(
long lPid long lPid
, wxSignal eSig , wxSignal eSig
, wxKillError* peError , wxKillError* peError
, int flags
) )
{ {
return((int)::DosKillProcess(0, (PID)lPid)); return((int)::DosKillProcess(0, (PID)lPid));

View File

@@ -126,8 +126,7 @@ bool wxSetEnv(const wxString& var, const wxChar *value)
// process management // process management
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// structure used to pass parameters from wxKill() to wxEnumFindByPidProc() int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
int wxKill(long pid, wxSignal sig, wxKillError *krc)
{ {
return 0; return 0;
} }

View File

@@ -200,9 +200,9 @@ void wxMilliSleep(unsigned long milliseconds)
// process management // 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 ) if ( !err )
*rc = wxKILL_OK; *rc = wxKILL_OK;
else else