diff --git a/BUILD b/BUILD index d4fcd4e8c89..c40ee518bba 100644 --- a/BUILD +++ b/BUILD @@ -84,6 +84,7 @@ cc_library( "src/core/support/string_posix.c", "src/core/support/string_win32.c", "src/core/support/subprocess_posix.c", + "src/core/support/subprocess_windows.c", "src/core/support/sync.c", "src/core/support/sync_posix.c", "src/core/support/sync_win32.c", @@ -1158,6 +1159,7 @@ objc_library( "src/core/support/string_posix.c", "src/core/support/string_win32.c", "src/core/support/subprocess_posix.c", + "src/core/support/subprocess_windows.c", "src/core/support/sync.c", "src/core/support/sync_posix.c", "src/core/support/sync_win32.c", diff --git a/Makefile b/Makefile index 40cbdfa8968..794778dae48 100644 --- a/Makefile +++ b/Makefile @@ -2235,6 +2235,7 @@ LIBGPR_SRC = \ src/core/support/string_posix.c \ src/core/support/string_win32.c \ src/core/support/subprocess_posix.c \ + src/core/support/subprocess_windows.c \ src/core/support/sync.c \ src/core/support/sync_posix.c \ src/core/support/sync_win32.c \ diff --git a/binding.gyp b/binding.gyp index 036d37b891f..133f8f48624 100644 --- a/binding.gyp +++ b/binding.gyp @@ -516,6 +516,7 @@ 'src/core/support/string_posix.c', 'src/core/support/string_win32.c', 'src/core/support/subprocess_posix.c', + 'src/core/support/subprocess_windows.c', 'src/core/support/sync.c', 'src/core/support/sync_posix.c', 'src/core/support/sync_win32.c', diff --git a/build.yaml b/build.yaml index 42776a73e93..f8d18fbb9a6 100644 --- a/build.yaml +++ b/build.yaml @@ -499,6 +499,7 @@ libs: - src/core/support/string_posix.c - src/core/support/string_win32.c - src/core/support/subprocess_posix.c + - src/core/support/subprocess_windows.c - src/core/support/sync.c - src/core/support/sync_posix.c - src/core/support/sync_win32.c diff --git a/gRPC.podspec b/gRPC.podspec index f33aa076e23..30b278798a1 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -151,6 +151,7 @@ Pod::Spec.new do |s| 'src/core/support/string_posix.c', 'src/core/support/string_win32.c', 'src/core/support/subprocess_posix.c', + 'src/core/support/subprocess_windows.c', 'src/core/support/sync.c', 'src/core/support/sync_posix.c', 'src/core/support/sync_win32.c', diff --git a/grpc.gemspec b/grpc.gemspec index 97abccae48c..585d3ec9090 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -134,6 +134,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/support/string_posix.c ) s.files += %w( src/core/support/string_win32.c ) s.files += %w( src/core/support/subprocess_posix.c ) + s.files += %w( src/core/support/subprocess_windows.c ) s.files += %w( src/core/support/sync.c ) s.files += %w( src/core/support/sync_posix.c ) s.files += %w( src/core/support/sync_win32.c ) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 7333405db3d..30edbc7251f 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -80,6 +80,7 @@ #define GPR_ARCH_64 1 #define GPR_GETPID_IN_PROCESS_H 1 #define GPR_WINSOCK_SOCKET 1 +#define GPR_WINDOWS_SUBPROCESS 1 #ifdef __GNUC__ #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 @@ -94,6 +95,7 @@ #define GPR_WIN32 1 #define GPR_GETPID_IN_PROCESS_H 1 #define GPR_WINSOCK_SOCKET 1 +#define GPR_WINDOWS_SUBPROCESS 1 #ifdef __GNUC__ #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 diff --git a/package.json b/package.json index 5b80a4875b2..0a3440e6e4c 100644 --- a/package.json +++ b/package.json @@ -491,6 +491,7 @@ "src/core/support/string_posix.c", "src/core/support/string_win32.c", "src/core/support/subprocess_posix.c", + "src/core/support/subprocess_windows.c", "src/core/support/sync.c", "src/core/support/sync_posix.c", "src/core/support/sync_win32.c", diff --git a/src/core/support/subprocess_windows.c b/src/core/support/subprocess_windows.c new file mode 100644 index 00000000000..d48c5437f0f --- /dev/null +++ b/src/core/support/subprocess_windows.c @@ -0,0 +1,141 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#ifdef GPR_WINDOWS_SUBPROCESS + +#include +#include +#include + +#include +#include +#include +#include "src/core/support/string.h" +#include "src/core/support/string_win32.h" + +struct gpr_subprocess { + PROCESS_INFORMATION pi; + int joined; + int interrupted; +}; + +const char *gpr_subprocess_binary_extension() { return ".exe"; } + +gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) { + gpr_subprocess *r; + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + char *args = gpr_strjoin_sep(argv, argc, " ", NULL); + TCHAR *args_tchar; + + args_tchar = gpr_char_to_tchar(args); + gpr_free(args); + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + memset(&pi, 0, sizeof(pi)); + + if (!CreateProcess(NULL, args_tchar, NULL, NULL, FALSE, + CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) { + gpr_free(args_tchar); + return NULL; + } + gpr_free(args_tchar); + + r = gpr_malloc(sizeof(gpr_subprocess)); + memset(r, 0, sizeof(*r)); + r->pi = pi; + return r; +} + +void gpr_subprocess_destroy(gpr_subprocess *p) { + if (p) { + if (!p->joined) { + gpr_subprocess_interrupt(p); + gpr_subprocess_join(p); + } + if (p->pi.hProcess) { + CloseHandle(p->pi.hProcess); + } + if (p->pi.hThread) { + CloseHandle(p->pi.hThread); + } + gpr_free(p); + } +} + +int gpr_subprocess_join(gpr_subprocess *p) { + DWORD dwExitCode; + if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) { + if (dwExitCode == STILL_ACTIVE) { + if (WaitForSingleObject(p->pi.hProcess, INFINITE) == WAIT_OBJECT_0) { + p->joined = 1; + goto getExitCode; + } + return -1; // failed to join + } else { + goto getExitCode; + } + } else { + return -1; // failed to get exit code + } + +getExitCode: + if (p->interrupted) { + return 0; + } + if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) { + return dwExitCode; + } else { + return -1; // failed to get exit code + } +} + +void gpr_subprocess_interrupt(gpr_subprocess *p) { + DWORD dwExitCode; + if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) { + if (dwExitCode == STILL_ACTIVE) { + gpr_log(GPR_INFO, "sending ctrl-break"); + GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, p->pi.dwProcessId); + p->joined = 1; + p->interrupted = 1; + } + } + return; +} + +#endif /* GPR_WINDOWS_SUBPROCESS */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index d26a8647dc9..708091df9f1 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -60,6 +60,7 @@ CORE_SOURCE_FILES = [ 'src/core/support/string_posix.c', 'src/core/support/string_win32.c', 'src/core/support/subprocess_posix.c', + 'src/core/support/subprocess_windows.c', 'src/core/support/sync.c', 'src/core/support/sync_posix.c', 'src/core/support/sync_win32.c', diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1585bdeac44..cd49a1980dc 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1139,6 +1139,7 @@ src/core/support/string.c \ src/core/support/string_posix.c \ src/core/support/string_win32.c \ src/core/support/subprocess_posix.c \ +src/core/support/subprocess_windows.c \ src/core/support/sync.c \ src/core/support/sync_posix.c \ src/core/support/sync_win32.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 1654228e396..aef0023a3e5 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -2916,6 +2916,7 @@ "src/core/support/string_win32.c", "src/core/support/string_win32.h", "src/core/support/subprocess_posix.c", + "src/core/support/subprocess_windows.c", "src/core/support/sync.c", "src/core/support/sync_posix.c", "src/core/support/sync_win32.c", diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index cba35888905..b20d6ff77f5 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -269,6 +269,8 @@ + + diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 1f8b09a1e9a..85d8ec86729 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -91,6 +91,9 @@ src\core\support + + src\core\support + src\core\support