// Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, // as published by the Free Software Foundation. // // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license // documentation. The authors of MySQL hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have included with MySQL. // // 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. /// @file safe_kill_win.cc /// /// Utility program used to signal a safe_process it's time to shutdown /// /// Usage: /// safe_kill #include #include #include #include #include int main(int argc, const char **argv) { // Ignore any signals signal(SIGINT, SIG_IGN); signal(SIGBREAK, SIG_IGN); signal(SIGTERM, SIG_IGN); if (argc != 3) { std::fprintf(stderr, "safe_kill \n"); std::exit(2); } DWORD pid = std::atoi(argv[1]); if (std::strcmp(argv[2], "mysqltest") == 0) { char event_name[64]; std::sprintf(event_name, "mysqltest[%d]stacktrace", pid); HANDLE stacktrace_request_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); if (stacktrace_request_event == NULL) { // Failed to open timeout event HANDLE mysqltest_process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid); // Check if the process is alive. if (mysqltest_process) std::fprintf(stderr, "Failed to open stacktrace_request_event %s, error = %d\n", event_name, GetLastError()); } else { if (SetEvent(stacktrace_request_event) == 0) { // Failed to set timeout event std::fprintf(stderr, "Failed to set event %s.\n", event_name); std::exit(3); } // A small delay of 4 seconds after setting timeout_event to allow the // stack printing to be completed before setting the shutdown_event. Sleep(4000); CloseHandle(stacktrace_request_event); } } char safe_process_name[32] = {0}; std::sprintf(safe_process_name, "safe_process[%d]", pid); int retry_open_event = 2; // Open the event to signal HANDLE shutdown_event; while ((shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, safe_process_name)) == NULL) { // Check if the process is alive, otherwise there is really // no sense to retry the open of the event. HANDLE process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid); if (!process) { // Already died std::exit(1); } DWORD exit_code; if (!GetExitCodeProcess(process, &exit_code)) { std::fprintf(stderr, "GetExitCodeProcess failed, pid= %d, err= %d\n", pid, GetLastError()); std::exit(1); } if (exit_code != STILL_ACTIVE) { // Already died CloseHandle(process); std::exit(2); } CloseHandle(process); if (retry_open_event--) Sleep(100); else { std::fprintf(stderr, "Failed to open shutdown_event '%s', error: %d\n", safe_process_name, GetLastError()); std::exit(3); } } if (SetEvent(shutdown_event) == 0) { std::fprintf(stderr, "Failed to signal shutdown_event '%s', error: %d\n", safe_process_name, GetLastError()); CloseHandle(shutdown_event); std::exit(4); } CloseHandle(shutdown_event); std::exit(0); }