cleanup and some fixes

This commit is contained in:
Dave Schuyler 2002-08-08 22:25:16 +00:00
parent a1c5c358f3
commit d64c8a66dc
2 changed files with 64 additions and 131 deletions

View File

@ -17,6 +17,7 @@
//
////////////////////////////////////////////////////////////////////
// This define tells the windows headers to include job objects:
#define _WIN32_WINNT 0x0500
#include "directd.h"
@ -38,11 +39,10 @@
#include "pset.h"
//#define old_directd
#undef old_directd
#ifdef old_directd //[
namespace {
// ...This section is part of the old stuff from the original implementation.
// The new stuff that uses job objects doesn't need this stuff:
// The following is from an MSDN example:
#define TA_FAILED 0
@ -132,121 +132,10 @@ namespace {
}
}
#else //][
namespace {
// The following is from an MSDN example:
#define TA_FAILED 0
#define TA_SUCCESS_CLEAN 1
#define TA_SUCCESS_KILL 2
#define TA_SUCCESS_16 3
HANDLE sgJobObject;
BOOL CALLBACK
TerminateAppEnum(HWND hwnd, LPARAM lParam) {
DWORD dwID;
GetWindowThreadProcessId(hwnd, &dwID);
if(dwID == (DWORD)lParam) {
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
return TRUE;
}
/*
DWORD WINAPI TerminateApp(DWORD dwPID, DWORD dwTimeout)
Purpose:
Shut down a 32-Bit Process
Parameters:
dwPID
Process ID of the process to shut down.
dwTimeout
Wait time in milliseconds before shutting down the process.
Return Value:
TA_FAILED - If the shutdown failed.
TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE.
TA_SUCCESS_KILL - if the process was shut down with
TerminateProcess().
*/
DWORD WINAPI
TerminateApp(DWORD dwPID, DWORD dwTimeout) {
HANDLE hProc;
DWORD dwRet;
// If we can't open the process with PROCESS_TERMINATE rights,
// then we give up immediately.
hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID);
if(hProc == NULL) {
return TA_FAILED;
}
// TerminateAppEnum() posts WM_CLOSE to all windows whose PID
// matches your process's.
EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)dwPID);
// Wait on the handle. If it signals, great. If it times out,
// then you kill it.
if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0) {
dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
} else {
dwRet = TA_SUCCESS_CLEAN;
}
CloseHandle(hProc);
return dwRet;
}
/*
Start an application with the command line cmd.
*/
void
StartApp(const string& cmd) {
static inited;
if (!inited) {
inited=1;
sgJobObject=CreateJobObject(0, 0);
if (!sgJobObject) {
nout<<"CreateProcess failed: no sgJobObject"<<endl;
}
}
DWORD pid=0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
if (CreateProcess(NULL, (char*)cmd.c_str(),
0, 0, 1, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED,
0, 0, &si, &pi)) {
// The process must be created with CREATE_SUSPENDED to
// give us a chance to get the handle into our sgJobObject
// before the child processes starts sub-processes.
if (!AssignProcessToJobObject(sgJobObject, pi.hProcess)) {
// ...The assign failed.
CloseHandle(pi.hProcess);
}
else { CloseHandle(pi.hProcess); } //?????
// Because we called CreateProcess with the CREATE_SUSPEND flag,
// we must explicitly resume the processes main thread.
if (ResumeThread(pi.hThread) == -1) {
cerr<<"StartApp ResumeThread Error: "<<GetLastError()<<endl;
}
CloseHandle(pi.hThread);
} else {
nout<<"CreateProcess failed: "<<cmd<<endl;
}
}
}
#endif //]
DirectD::DirectD() :
_reader(&_cm, 1), _writer(&_cm, 0), _listener(&_cm, 0),
_shutdown(false) {
_jobObject(0), _shutdown(false), _useOldStuff(false) {
}
DirectD::~DirectD() {
@ -326,17 +215,49 @@ DirectD::server_ready(const string& client_host, int port) {
void
DirectD::start_app(const string& cmd) {
nout<<"start_app(cmd="<<cmd<<")"<<endl;
#ifdef old_directd //[
if (_useOldStuff) {
_pids.push_back(StartApp(cmd));
nout<<" pid="<<_pids.back()<<endl;
#else //][
StartApp(cmd);
#endif //]
} else {
if (!_jobObject) {
_jobObject=CreateJobObject(0, 0);
if (!_jobObject) {
nout<<"CreateProcess failed: no _jobObject: "<<GetLastError()<<endl;
return;
}
}
DWORD pid=0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
if (CreateProcess(NULL, (char*)cmd.c_str(),
0, 0, 1, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED,
0, 0, &si, &pi)) {
// The process must be created with CREATE_SUSPENDED to
// give us a chance to get the handle into our sgJobObject
// before the child processes starts sub-processes.
if (!AssignProcessToJobObject(_jobObject, pi.hProcess)) {
// ...The assign failed.
cerr<<"StartJob AssignProcessToJobObject Error: "<<GetLastError()<<endl;
}
CloseHandle(pi.hProcess); //?????
// Because we called CreateProcess with the CREATE_SUSPEND flag,
// we must explicitly resume the processes main thread.
if (ResumeThread(pi.hThread) == -1) {
cerr<<"StartJob ResumeThread Error: "<<GetLastError()<<endl;
}
CloseHandle(pi.hThread);
} else {
nout<<"StartJob CreateProcess failed: "<<cmd<<endl;
}
}
}
void
DirectD::kill_app(int index) {
#ifdef old_directd //[
if (_useOldStuff) {
int i = _pids.size() - 1 - index % _pids.size();
PidStack::iterator pi = _pids.begin() + i;
if (pi!=_pids.end()) {
@ -344,27 +265,30 @@ DirectD::kill_app(int index) {
TerminateApp((*pi), 1000);
_pids.erase(pi);
}
#else //][
} else {
cerr<<"kill_app(index) not implemented, calling kill_all() instead."<<endl;
kill_all();
#endif //]
}
}
void
DirectD::kill_all() {
#ifdef old_directd //[
if (_useOldStuff) {
PidStack::reverse_iterator pi;
for (pi = _pids.rbegin(); pi != _pids.rend(); ++pi) {
nout<<"trying kill "<<(*pi)<<endl;
TerminateApp((*pi), 1000);
}
_pids.clear();
#else //][
if (TerminateJobObject(sgJobObject, 0)) {
cerr<<"true TerminateJobObject"<<endl;
} else {
cerr<<"false TerminateJobObject"<<endl;
} else {
if (!_jobObject) {
cerr<<"kill_all(): No open _jobObject"<<endl;
} else if (!TerminateJobObject(_jobObject, 0)) {
cerr<<"kill_all() TerminateJobObject Error: "<<GetLastError()<<endl;
}
#endif //]
CloseHandle(_jobObject);
_jobObject=0;
}
}
void

View File

@ -28,6 +28,7 @@
#ifdef CPPPARSER //[
// hack for interrogate
typedef int intptr_t;
typedef int HANDLE;
#endif //]
@ -144,11 +145,19 @@ protected:
ConnectionWriter _writer;
QueuedConnectionListener _listener;
// Start of old stuff:
// This is used to switch to the original method of
// starting applications. It can be used on old systems
// that don't support job objects. Eventually this stuff
// should be removed.
bool _useOldStuff;
typedef pvector< long /*intptr_t*/ > PidStack;
PidStack _pids;
// End of old stuff
typedef pset< PT(Connection) > ConnectionSet;
ConnectionSet _connections;
HANDLE _jobObject;
bool _shutdown;
void check_for_new_clients();