|
|||||||||||
|
bk commit into 5.1 tree (iggy:1.2567)
From: Ignacio Galarza <iggy(at)mysql.com>
Date: Fri Sep 28 2007 - 18:43:58 EDT
ChangeSet@1.2567, 2007-09-28 18:43:46-04:00, iggy@alf.(none) +3 -0 WL#4072 Move mysql_kill from Connector /MJX to the Server
extra/CMakeLists.txt@1.10, 2007-09-28 18:43:41-04:00, iggy@alf.(none) +4 -0 WL#4072 Move mysql_kill from Connector /MJX to the Server
extra/Makefile.am@1.46, 2007-09-28 18:43:41-04:00, iggy@alf.(none) +1 -1 WL#4072 Move mysql_kill from Connector /MJX to the Server
extra/mysql_kill.cpp@1.1, 2007-09-28 18:43:41-04:00, iggy@alf.(none) +244 -0 WL#4072 Move mysql_kill from Connector /MJX to the Server
extra/mysql_kill.cpp@1.0, 2007-09-28 18:43:41-04:00, iggy@alf.(none) +0 -0 diff -Nrup a/extra/CMakeLists.txt b/extra/CMakeLists.txt --- a/extra/CMakeLists.txt 2007-08-03 16:50:34 -04:00@@ -47,6 +47,10 @@ TARGET_LINK_LIBRARIES(perror strings mys ADD_EXECUTABLE(replace replace.c) TARGET_LINK_LIBRARIES(replace strings mysys debug dbug wsock32) +ADD_EXECUTABLE(mysql_kill mysql_kill.cpp) --- a/extra/Makefile.am 2007-02-22 10:43:57 -05:00@@ -0,0 +1,244 @@ +/* + Copyright (C) 2007 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ + +// mysql_kill.cpp : a variation on the unix "kill" for use with mysqld on windows +// Author: Eric Herman +// Adapted from original "kill.cpp" by Eric Herman and Kendrick Shaw. +// SafeTerminateProcess Adaptded by code written by Reggie Burnett. + +// SIGHUP is replaced by OpenEvent(EVENT_MODIFY_STATE, FALSE, "MySQLShutdown<PID>"); + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include <stdio.h> +#include <iostream> +#include <process.h> +#include <windows.h> +#include <windef.h> +#include <process.h> + +typedef BOOL (*process_func)(HANDLE hProcess, UINT uExitCode); + +// ------------------------------------ + +BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode) +{ + DWORD dwTID, dwCode, dwErr = 0; + HANDLE hProcessDup = INVALID_HANDLE_VALUE; + HANDLE hRT = NULL; + HINSTANCE hKernel = GetModuleHandle("Kernel32"); + BOOL bSuccess = FALSE; + + // warning C4312: 'type cast' : + // conversion from 'UINT' to 'PVOID' of greater size + // FIXME: Since our usage is always ZERO maybe we don't care, + // but still it would be nice to have a clean compile that deals + // with this warning the "right" way. + PVOID pvExitCode = (PVOID)uExitCode; + + BOOL bDup = DuplicateHandle(GetCurrentProcess(), + hProcess, + GetCurrentProcess(), + &hProcessDup, + PROCESS_ALL_ACCESS, + FALSE, + 0); + + // Detect the special case where the process is + // already dead... + if ( GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) + && (dwCode == STILL_ACTIVE) ) + { + FARPROC pfnExitProc; + + pfnExitProc = GetProcAddress(hKernel, "ExitProcess"); + + hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess, + NULL, + 0, + (LPTHREAD_START_ROUTINE)pfnExitProc, + pvExitCode, + 0, + &dwTID); + + if ( hRT == NULL ) + { + dwErr = GetLastError(); + } + } + else + { + dwErr = ERROR_PROCESS_ABORTED; + } + + if ( hRT ) + { + // Must wait (miliseconds) for process to terminate to + // guarantee that it has exited... + WaitForSingleObject((bDup) ? hProcessDup : hProcess, 20 * 1000); + // WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE); + + CloseHandle(hRT); + bSuccess = TRUE; + } + + if ( bDup ) + { + CloseHandle(hProcessDup); + } + + if ( !bSuccess ) + { + SetLastError(dwErr); + } + return bSuccess; +} + +// ------------------------------------ + +// return 0 on success or error code +int ApplyToProcess(DWORD dwDesiredAccess, DWORD process_id, process_func pfunc) +{ + UINT uExitCode = 0; + + HANDLE h_process = OpenProcess(dwDesiredAccess, FALSE, process_id); + + if (h_process == NULL) + { + return GetLastError(); + } + + BOOL return_val= pfunc(h_process, uExitCode); + + CloseHandle(h_process); + + return return_val ? (int) uExitCode : GetLastError(); +} + +// return 0 on success or error code +int OpenAndSetEvent(DWORD dwDesiredAccess, const char* eventName) +{ + HANDLE hEvent= OpenEvent(dwDesiredAccess, FALSE, eventName); + if (hEvent == NULL) + { + fprintf(stderr, "No HANDLE %s", eventName); + // fprintf(stderr, "\nLast Error: %d", GetLastError()); + return GetLastError(); + } + SetEvent(hEvent); + CloseHandle(hEvent); + return 0; +} + +// return 0 on success or error code +int Terminate(DWORD pid) +{ + // fprint(stderr, "SafeTerminateProcess %d", pid); + int safe = ApplyToProcess(PROCESS_TERMINATE, pid, &SafeTerminateProcess); + if( safe == 0 ) + { + return 0; + } + fprintf(stderr, "TerminateProcess %d", pid); + return ApplyToProcess(PROCESS_TERMINATE, pid, (process_func)&TerminateProcess); +} + +BOOL KnownProcessInner(HANDLE h_process, UINT uExitCode) +{ + // already returned if process doesn't exist + return TRUE; +} + +// return 0 on success or error code +int KnownProcess(DWORD dwDesiredAccess, DWORD pid) +{ + return ApplyToProcess(dwDesiredAccess, pid, &KnownProcessInner); +} + +// return 0 on success or error code +int KnownProcess(DWORD pid) +{ + return KnownProcess(PROCESS_TERMINATE, pid); +} + + +// ------------------------------------ + + +void Usage(const char *argv0) +{ + char usage[2048]; + sprintf_s(usage, 2048, "USAGE: %s [-0 -9] PID", argv0); + printf(usage); +} + +int SetEventMySQLShutdown(DWORD pid) +{ + // If shutdown_event_name as defined mysqld.cc changes + // from in "MySQLShutdown<PID>" we must change this also. + // Perhaps the name should be moved to a constant and + // in a header file that we could include here, too? + char buff[60]; + sprintf_s(buff, 60, "MySQLShutdown%d", pid); + return OpenAndSetEvent(EVENT_MODIFY_STATE, buff); +} + +int main(int argc, const char** argv) +{ + DWORD pid = 0; + + if ((argc == 2) && (sscanf_s(argv[1], "%30u", &pid) == 1)) + { + return SetEventMySQLShutdown(pid); + } + + + // 0 == NULL (process exists) + // 1 == HUP (hang up) + // 2 == INT (interrupt) + // 3 == QUIT (quit) + // 6 == ABRT (abort) + // 9 == KILL (non-catchable, non-ignorable kill) + // 14 == ALRM (alarm clock) + // 15 == TERM (software termination signal) + + if ((argc == 3) && (sscanf_s(argv[2], "%30u", &pid) == 1)) + { + if (strcmp(argv[1], "-0")==0) + { + // 0 == NUL (process exists) + return KnownProcess(pid); + } + + if (strcmp(argv[1], "-9")==0) + { + // 9 == KILL (non-catchable, non-ignorable kill) + return Terminate(pid); + } + + // We could elect to treat ALL other signals as nice shutdown + // (perhaps excluding 14 (ALRM)) and not just HUP and QUIT. + if ((strcmp(argv[1], "-1")==0) || (strcmp(argv[1], "-3")==0)) + { + return SetEventMySQLShutdown(pid); + } + } + + Usage(argv[0]); + return 1; +} -- MySQL Code Commits Mailing List For list archives: http://lists.mysql.com/commits To unsubscribe: http://lists.mysql.com/commits?unsub=lists@pantek.comReceived on Fri Sep 28 18:44:05 2007 This archive was generated by hypermail 2.1.8 : Sun Oct 07 2007 - 09:44:57 EDT |
||||||||||
|
|||||||||||