From 47788360221cfe3045947fb7129d5a561100e7eb Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 2 Sep 2011 18:47:15 +0000 Subject: [PATCH] - Win compile fixes svn path=/trunk/boinc/; revision=24122 --- client/app_start.cpp | 2 +- client/client_state.cpp | 2 +- lib/proc_control.cpp | 404 +++++++++++++++++++----------------- samples/wrapper/wrapper.cpp | 2 +- win_build/boinc_cli.vcproj | 8 + 5 files changed, 220 insertions(+), 198 deletions(-) diff --git a/client/app_start.cpp b/client/app_start.cpp index 2137d4750f..2f9c44ab6a 100644 --- a/client/app_start.cpp +++ b/client/app_start.cpp @@ -84,7 +84,7 @@ using std::string; #ifdef _WIN32 -#include "proc_control.h" +#include "run_app_windows.h" #endif #include "cs_proxy.h" diff --git a/client/client_state.cpp b/client/client_state.cpp index acbe17839e..1a59d49a90 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -44,7 +44,7 @@ #include "error_numbers.h" #include "filesys.h" #ifdef _WIN32 -#include "proc_control.h" +#include "run_app_windows.h" #endif #include "file_names.h" diff --git a/lib/proc_control.cpp b/lib/proc_control.cpp index a9d7cff358..40a55dbbef 100644 --- a/lib/proc_control.cpp +++ b/lib/proc_control.cpp @@ -1,195 +1,209 @@ -// This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2011 University of California -// -// BOINC is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// BOINC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with BOINC. If not, see . - -#include -#include -#include -#include - -#include "procinfo.h" - -#include "proc_control.h" - -using std::vector; - -static void get_descendants_aux(PROC_MAP& pm, int pid, vector& pids) { - PROC_MAP::iterator i = pm.find(pid); - if (i == pm.end()) return; - for (unsigned int j=0; jsecond.children.size(); j++) { - int child_pid = i->second.children[j]; - pids.push_back(child_pid); - get_descendants_aux(pm, child_pid, pids); - } -} - -// return a list of all descendants of the given process -// -void get_descendants(int pid, vector& pids) { - int retval; - PROC_MAP pm; - pids.clear(); - retval = procinfo_setup(pm); - if (retval) return; - get_descendants_aux(pm, pid, pids); -} - -bool any_process_exists(vector& pids) { - int status; - for (unsigned int i=0; i= 0) { - return true; - } - } - return false; -} - -void kill_all(vector& pids) { - for (unsigned int i=0; i descendants; - // on Win, kill descendants directly - // - get_descendants(GetCurrentProcessId(), descendants); - kill_all(descendants); -} -#else -// Same, but if child_pid is nonzero, give it a chance to exit gracefully on Unix -// -void kill_descendants(int child_pid) { - vector descendants; - // on Unix, ask main process nicely. - // it descendants still exist after 10 sec, use the nuclear option - // - get_descendants(getpid(), descendants); - if (child_pid) { - ::kill(child_pid, SIGTERM); - for (int i=0; i<10; i++) { - if (!any_process_exists(descendants)) { - return; - } - sleep(1); - } - kill_all(descendants); - // kill any processes that might have been created - // in the last 10 secs - get_descendants(getpid(), descendants); - } - kill_all(descendants); -} -#endif - -void suspend_or_resume_all(vector& pids, bool resume) { - for (unsigned int i=0; i descendants; - if (!pid) { -#ifdef _WIN32 - pid = GetCurrentProcessId(); -#else - pid = getpid(); -#endif - } - get_descendants(pid, descendants); - suspend_or_resume_all(descendants, resume); -} - -void suspend_or_resume_process(int pid, bool resume) { -#ifdef _WIN32 - suspend_or_resume_threads(pid, 0, resume); -#else - ::kill(pid, resume?SIGCONT:SIGSTOP); -#endif - -} +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2011 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#include +#ifdef _WIN32 +#include "diagnostics.h" +#ifdef __STDWX_H__ +#include "stdwx.h" +#else +#include "boinc_win.h" +#include "win_util.h" +#endif +#else +#include +#include +#include +#endif + +#include "procinfo.h" + +#include "proc_control.h" + +using std::vector; + +static void get_descendants_aux(PROC_MAP& pm, int pid, vector& pids) { + PROC_MAP::iterator i = pm.find(pid); + if (i == pm.end()) return; + for (unsigned int j=0; jsecond.children.size(); j++) { + int child_pid = i->second.children[j]; + pids.push_back(child_pid); + get_descendants_aux(pm, child_pid, pids); + } +} + +// return a list of all descendants of the given process +// +void get_descendants(int pid, vector& pids) { + int retval; + PROC_MAP pm; + pids.clear(); + retval = procinfo_setup(pm); + if (retval) return; + get_descendants_aux(pm, pid, pids); +} + +#ifdef _WIN32 +// signature of OpenThread() +// +typedef HANDLE (WINAPI *tOT)( + DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId +); + +// Suspend or resume the threads in a given process, +// but don't suspend 'calling_thread'. +// +// The only way to do this on Windows is to enumerate +// all the threads in the entire system, +// and find those belonging to the process (ugh!!) +// + +int suspend_or_resume_threads( + DWORD pid, DWORD calling_thread_id, bool resume +) { + HANDLE threads, thread; + static HMODULE hKernel32Lib = NULL; + THREADENTRY32 te = {0}; + static tOT pOT = NULL; + + // Dynamically link to the proper function pointers. + if (!hKernel32Lib) { + hKernel32Lib = GetModuleHandleA("kernel32.dll"); + } + if (!pOT) { + pOT = (tOT) GetProcAddress( hKernel32Lib, "OpenThread" ); + } + + if (!pOT) { + return -1; + } + + threads = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (threads == INVALID_HANDLE_VALUE) return -1; + + te.dwSize = sizeof(THREADENTRY32); + if (!Thread32First(threads, &te)) { + CloseHandle(threads); + return -1; + } + + do { + if (!diagnostics_is_thread_exempt_suspend(te.th32ThreadID)) continue; + if (te.th32ThreadID == calling_thread_id) continue; + if (te.th32OwnerProcessID == pid) { + thread = pOT(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID); + resume ? ResumeThread(thread) : SuspendThread(thread); + CloseHandle(thread); + } + } while (Thread32Next(threads, &te)); + + CloseHandle (threads); + + return 0; +} + +#else + +bool any_process_exists(vector& pids) { + int status; + for (unsigned int i=0; i= 0) { + return true; + } + } + return false; +} + +void kill_all(vector& pids) { + for (unsigned int i=0; i descendants; + // on Win, kill descendants directly + // + get_descendants(GetCurrentProcessId(), descendants); + kill_all(descendants); +} +#else +// Same, but if child_pid is nonzero, give it a chance to exit gracefully on Unix +// +void kill_descendants(int child_pid) { + vector descendants; + // on Unix, ask main process nicely. + // it descendants still exist after 10 sec, use the nuclear option + // + get_descendants(getpid(), descendants); + if (child_pid) { + ::kill(child_pid, SIGTERM); + for (int i=0; i<10; i++) { + if (!any_process_exists(descendants)) { + return; + } + sleep(1); + } + kill_all(descendants); + // kill any processes that might have been created + // in the last 10 secs + get_descendants(getpid(), descendants); + } + kill_all(descendants); +} +#endif + +void suspend_or_resume_all(vector& pids, bool resume) { + for (unsigned int i=0; i descendants; + if (!pid) { +#ifdef _WIN32 + pid = GetCurrentProcessId(); +#else + pid = getpid(); +#endif + } + get_descendants(pid, descendants); + suspend_or_resume_all(descendants, resume); +} + +void suspend_or_resume_process(int pid, bool resume) { +#ifdef _WIN32 + suspend_or_resume_threads(pid, 0, resume); +#else + ::kill(pid, resume?SIGCONT:SIGSTOP); +#endif + +} diff --git a/samples/wrapper/wrapper.cpp b/samples/wrapper/wrapper.cpp index 3cbe24de7b..b70850912b 100644 --- a/samples/wrapper/wrapper.cpp +++ b/samples/wrapper/wrapper.cpp @@ -41,7 +41,7 @@ #include #endif -#include "procinfo.h" +#include "proc_control.h" #include "boinc_api.h" #include "diagnostics.h" #include "filesys.h" diff --git a/win_build/boinc_cli.vcproj b/win_build/boinc_cli.vcproj index 610ef0c676..5d08bef9c4 100644 --- a/win_build/boinc_cli.vcproj +++ b/win_build/boinc_cli.vcproj @@ -735,6 +735,10 @@ RelativePath="..\client\rr_sim.cpp" > + + @@ -892,6 +896,10 @@ RelativePath="..\client\rr_sim.h" > + +