// Processes.cpp //#include #if defined(_WIN32) || defined(_WIN64) #define WIN32_LEAN_AND_MEAN #include #define TIMEOUT_PERIOD 1000 #elif defined(linux) || defined(__linux) || (defined(__APPLE__) && defined(__MACH__)) #include #include #include #include #define INITIAL_TIMEOUT 50000 #define TIMEOUT_LIMIT 5 #endif #include "ErrorHandling.hpp" #include "cipres-jni.h" using namespace CipresJNI; #if defined(_WIN32) || defined(_WIN64) // SendWindowClose static BOOL CALLBACK SendWindowClose(HWND handle, LPARAM param) { unsigned long pid; ::GetWindowThreadProcessId(handle, &pid); if(pid == static_cast(param)) ::PostMessage(handle, WM_CLOSE, NULL, NULL); return TRUE; } #elif defined(linux) || defined(__linux) || (defined(__APPLE__) && defined(__MACH__)) // ProcessExists static bool ProcessExists(int pid) throw() { int result = ::kill(pid, 0); return result == 0 || errno == EPERM; } #endif // Java_org_cipres_jni_Processes_getProcessID jint JNICALL Java_org_cipres_jni_Processes_getProcessID(JNIEnv *env, jclass obj) { #if defined(_WIN32) || defined(_WIN64) return ::GetCurrentProcessId(); #elif defined(linux) || defined(__linux) || (defined(__APPLE__) && defined(__MACH__)) return ::getpid(); #endif } // Java_org_cipres_jni_Processes_processExists jboolean JNICALL Java_org_cipres_jni_Processes_processExists(JNIEnv *env, jclass, jint pid) { #if defined(_WIN32) || defined(_WIN64) if(pid == 0) return true; HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if(process != NULL) { ::CloseHandle(process); return true; } else if(::GetLastError() == ERROR_ACCESS_DENIED) return true; else return false; #elif defined(linux) || defined(__linux) || (defined(__APPLE__) && defined(__MACH__)) return ProcessExists(pid); #endif } // Java_org_cipres_jni_Processes_killProcess void JNICALL Java_org_cipres_jni_Processes_killProcess(JNIEnv *env, jclass obj, jint pid, jboolean force) { #if defined(_WIN32) || defined(_WIN64) HANDLE process; if((process = ::OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pid)) == NULL) { long error_code = ::GetLastError(); if(error_code != ERROR_ACCESS_DENIED) { ThrowSystemError(env, error_code); return; } } ::EnumWindows(SendWindowClose, pid); if(!force) { ::CloseHandle(process); return; } if(::WaitForSingleObject(process, TIMEOUT_PERIOD) != WAIT_OBJECT_0) ::TerminateProcess(process, -1); ::CloseHandle(process); #elif defined(linux) || defined(__linux) || (defined(__APPLE__) && defined(__MACH__)) if(::kill(pid, SIGTERM) != 0) { int error_code = errno; if(error_code == ESRCH) ThrowError(env, JAVA_CLASS_ILLEGAL_ARG, "No such process"); else ThrowSystemError(env, error_code); return; } if(!force) return; unsigned int wait_period = INITIAL_TIMEOUT; for(int i = 0 ; i < TIMEOUT_LIMIT ; i++) { ::usleep(wait_period); if(!ProcessExists(pid)) return; wait_period *= 2; } ::kill(pid, SIGKILL); #endif }