|
17 | 17 | // |
18 | 18 | //////////////////////////////////////////////////////////////////// |
19 | 19 |
|
| 20 | +// This define tells the windows headers to include job objects: |
20 | 21 | #define _WIN32_WINNT 0x0500 |
21 | 22 |
|
22 | 23 | #include "directd.h" |
|
38 | 39 |
|
39 | 40 | #include "pset.h" |
40 | 41 |
|
41 | | -//#define old_directd |
42 | | -#undef old_directd |
43 | | - |
44 | | -#ifdef old_directd //[ |
45 | 42 | namespace { |
| 43 | + // ...This section is part of the old stuff from the original implementation. |
| 44 | + // The new stuff that uses job objects doesn't need this stuff: |
| 45 | + |
46 | 46 | // The following is from an MSDN example: |
47 | 47 |
|
48 | 48 | #define TA_FAILED 0 |
@@ -132,121 +132,10 @@ namespace { |
132 | 132 | } |
133 | 133 |
|
134 | 134 | } |
135 | | -#else //][ |
136 | | -namespace { |
137 | | - // The following is from an MSDN example: |
138 | | - |
139 | | - #define TA_FAILED 0 |
140 | | - #define TA_SUCCESS_CLEAN 1 |
141 | | - #define TA_SUCCESS_KILL 2 |
142 | | - #define TA_SUCCESS_16 3 |
143 | | - |
144 | | - HANDLE sgJobObject; |
145 | | - |
146 | | - BOOL CALLBACK |
147 | | - TerminateAppEnum(HWND hwnd, LPARAM lParam) { |
148 | | - DWORD dwID; |
149 | | - GetWindowThreadProcessId(hwnd, &dwID); |
150 | | - if(dwID == (DWORD)lParam) { |
151 | | - PostMessage(hwnd, WM_CLOSE, 0, 0); |
152 | | - } |
153 | | - return TRUE; |
154 | | - } |
155 | | - |
156 | | - /* |
157 | | - DWORD WINAPI TerminateApp(DWORD dwPID, DWORD dwTimeout) |
158 | | -
|
159 | | - Purpose: |
160 | | - Shut down a 32-Bit Process |
161 | | -
|
162 | | - Parameters: |
163 | | - dwPID |
164 | | - Process ID of the process to shut down. |
165 | | -
|
166 | | - dwTimeout |
167 | | - Wait time in milliseconds before shutting down the process. |
168 | | -
|
169 | | - Return Value: |
170 | | - TA_FAILED - If the shutdown failed. |
171 | | - TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE. |
172 | | - TA_SUCCESS_KILL - if the process was shut down with |
173 | | - TerminateProcess(). |
174 | | - */ |
175 | | - DWORD WINAPI |
176 | | - TerminateApp(DWORD dwPID, DWORD dwTimeout) { |
177 | | - HANDLE hProc; |
178 | | - DWORD dwRet; |
179 | | - |
180 | | - // If we can't open the process with PROCESS_TERMINATE rights, |
181 | | - // then we give up immediately. |
182 | | - hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID); |
183 | | - if(hProc == NULL) { |
184 | | - return TA_FAILED; |
185 | | - } |
186 | | - |
187 | | - // TerminateAppEnum() posts WM_CLOSE to all windows whose PID |
188 | | - // matches your process's. |
189 | | - EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)dwPID); |
190 | | - |
191 | | - // Wait on the handle. If it signals, great. If it times out, |
192 | | - // then you kill it. |
193 | | - if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0) { |
194 | | - dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED); |
195 | | - } else { |
196 | | - dwRet = TA_SUCCESS_CLEAN; |
197 | | - } |
198 | | - CloseHandle(hProc); |
199 | | - |
200 | | - return dwRet; |
201 | | - } |
202 | | - |
203 | | - /* |
204 | | - Start an application with the command line cmd. |
205 | | - */ |
206 | | - void |
207 | | - StartApp(const string& cmd) { |
208 | | - static inited; |
209 | | - if (!inited) { |
210 | | - inited=1; |
211 | | - sgJobObject=CreateJobObject(0, 0); |
212 | | - if (!sgJobObject) { |
213 | | - nout<<"CreateProcess failed: no sgJobObject"<<endl; |
214 | | - } |
215 | | - } |
216 | | - DWORD pid=0; |
217 | | - STARTUPINFO si; |
218 | | - PROCESS_INFORMATION pi; |
219 | | - ZeroMemory(&si, sizeof(STARTUPINFO)); |
220 | | - si.cb = sizeof(STARTUPINFO); |
221 | | - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); |
222 | | - if (CreateProcess(NULL, (char*)cmd.c_str(), |
223 | | - 0, 0, 1, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED, |
224 | | - 0, 0, &si, &pi)) { |
225 | | - // The process must be created with CREATE_SUSPENDED to |
226 | | - // give us a chance to get the handle into our sgJobObject |
227 | | - // before the child processes starts sub-processes. |
228 | | - if (!AssignProcessToJobObject(sgJobObject, pi.hProcess)) { |
229 | | - // ...The assign failed. |
230 | | - CloseHandle(pi.hProcess); |
231 | | - } |
232 | | - else { CloseHandle(pi.hProcess); } //????? |
233 | | - // Because we called CreateProcess with the CREATE_SUSPEND flag, |
234 | | - // we must explicitly resume the processes main thread. |
235 | | - if (ResumeThread(pi.hThread) == -1) { |
236 | | - cerr<<"StartApp ResumeThread Error: "<<GetLastError()<<endl; |
237 | | - } |
238 | | - CloseHandle(pi.hThread); |
239 | | - } else { |
240 | | - nout<<"CreateProcess failed: "<<cmd<<endl; |
241 | | - } |
242 | | - } |
243 | | - |
244 | | -} |
245 | | -#endif //] |
246 | 135 |
|
247 | 136 | DirectD::DirectD() : |
248 | 137 | _reader(&_cm, 1), _writer(&_cm, 0), _listener(&_cm, 0), |
249 | | - _shutdown(false) { |
| 138 | + _jobObject(0), _shutdown(false), _useOldStuff(false) { |
250 | 139 | } |
251 | 140 |
|
252 | 141 | DirectD::~DirectD() { |
@@ -326,45 +215,80 @@ DirectD::server_ready(const string& client_host, int port) { |
326 | 215 | void |
327 | 216 | DirectD::start_app(const string& cmd) { |
328 | 217 | nout<<"start_app(cmd="<<cmd<<")"<<endl; |
329 | | - #ifdef old_directd //[ |
| 218 | + if (_useOldStuff) { |
330 | 219 | _pids.push_back(StartApp(cmd)); |
331 | 220 | nout<<" pid="<<_pids.back()<<endl; |
332 | | - #else //][ |
333 | | - StartApp(cmd); |
334 | | - #endif //] |
| 221 | + } else { |
| 222 | + if (!_jobObject) { |
| 223 | + _jobObject=CreateJobObject(0, 0); |
| 224 | + if (!_jobObject) { |
| 225 | + nout<<"CreateProcess failed: no _jobObject: "<<GetLastError()<<endl; |
| 226 | + return; |
| 227 | + } |
| 228 | + } |
| 229 | + DWORD pid=0; |
| 230 | + STARTUPINFO si; |
| 231 | + PROCESS_INFORMATION pi; |
| 232 | + ZeroMemory(&si, sizeof(STARTUPINFO)); |
| 233 | + si.cb = sizeof(STARTUPINFO); |
| 234 | + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); |
| 235 | + if (CreateProcess(NULL, (char*)cmd.c_str(), |
| 236 | + 0, 0, 1, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED, |
| 237 | + 0, 0, &si, &pi)) { |
| 238 | + // The process must be created with CREATE_SUSPENDED to |
| 239 | + // give us a chance to get the handle into our sgJobObject |
| 240 | + // before the child processes starts sub-processes. |
| 241 | + if (!AssignProcessToJobObject(_jobObject, pi.hProcess)) { |
| 242 | + // ...The assign failed. |
| 243 | + cerr<<"StartJob AssignProcessToJobObject Error: "<<GetLastError()<<endl; |
| 244 | + } |
| 245 | + CloseHandle(pi.hProcess); //????? |
| 246 | + // Because we called CreateProcess with the CREATE_SUSPEND flag, |
| 247 | + // we must explicitly resume the processes main thread. |
| 248 | + if (ResumeThread(pi.hThread) == -1) { |
| 249 | + cerr<<"StartJob ResumeThread Error: "<<GetLastError()<<endl; |
| 250 | + } |
| 251 | + CloseHandle(pi.hThread); |
| 252 | + } else { |
| 253 | + nout<<"StartJob CreateProcess failed: "<<cmd<<endl; |
| 254 | + } |
| 255 | + } |
335 | 256 | } |
336 | 257 |
|
337 | 258 | void |
338 | 259 | DirectD::kill_app(int index) { |
339 | | - #ifdef old_directd //[ |
| 260 | + if (_useOldStuff) { |
340 | 261 | int i = _pids.size() - 1 - index % _pids.size(); |
341 | 262 | PidStack::iterator pi = _pids.begin() + i; |
342 | 263 | if (pi!=_pids.end()) { |
343 | 264 | nout<<"trying kill "<<(*pi)<<endl; |
344 | 265 | TerminateApp((*pi), 1000); |
345 | 266 | _pids.erase(pi); |
346 | 267 | } |
347 | | - #else //][ |
| 268 | + } else { |
| 269 | + cerr<<"kill_app(index) not implemented, calling kill_all() instead."<<endl; |
348 | 270 | kill_all(); |
349 | | - #endif //] |
| 271 | + } |
350 | 272 | } |
351 | 273 |
|
352 | 274 | void |
353 | 275 | DirectD::kill_all() { |
354 | | - #ifdef old_directd //[ |
| 276 | + if (_useOldStuff) { |
355 | 277 | PidStack::reverse_iterator pi; |
356 | 278 | for (pi = _pids.rbegin(); pi != _pids.rend(); ++pi) { |
357 | 279 | nout<<"trying kill "<<(*pi)<<endl; |
358 | 280 | TerminateApp((*pi), 1000); |
359 | 281 | } |
360 | 282 | _pids.clear(); |
361 | | - #else //][ |
362 | | - if (TerminateJobObject(sgJobObject, 0)) { |
363 | | - cerr<<"true TerminateJobObject"<<endl; |
364 | | - } else { |
365 | | - cerr<<"false TerminateJobObject"<<endl; |
| 283 | + } else { |
| 284 | + if (!_jobObject) { |
| 285 | + cerr<<"kill_all(): No open _jobObject"<<endl; |
| 286 | + } else if (!TerminateJobObject(_jobObject, 0)) { |
| 287 | + cerr<<"kill_all() TerminateJobObject Error: "<<GetLastError()<<endl; |
366 | 288 | } |
367 | | - #endif //] |
| 289 | + CloseHandle(_jobObject); |
| 290 | + _jobObject=0; |
| 291 | + } |
368 | 292 | } |
369 | 293 |
|
370 | 294 | void |
|
0 commit comments