blob: 6afbefeb2b30cca7bf1d06008db0a5ef71a48a34 [file] [log] [blame]
Nicolas "Pixel" Noble4fba2862016-01-31 07:00:53 +01001/*
2 *
Nicolas "Pixel" Nobled7933102016-02-01 01:22:25 +01003 * Copyright 2016, Google Inc.
Nicolas "Pixel" Noble4fba2862016-01-31 07:00:53 +01004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include <grpc/support/port_platform.h>
35
36#ifdef GPR_WINDOWS_SUBPROCESS
37
Nicolas "Pixel" Noble4fba2862016-01-31 07:00:53 +010038#include <string.h>
39#include <tchar.h>
Craig Tillerf40df232016-03-25 13:38:14 -070040#include <windows.h>
Nicolas "Pixel" Noble4fba2862016-01-31 07:00:53 +010041
42#include <grpc/support/alloc.h>
43#include <grpc/support/log.h>
44#include <grpc/support/subprocess.h>
45#include "src/core/support/string.h"
46#include "src/core/support/string_win32.h"
47
48struct gpr_subprocess {
49 PROCESS_INFORMATION pi;
50 int joined;
51 int interrupted;
52};
53
54const char *gpr_subprocess_binary_extension() { return ".exe"; }
55
56gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
57 gpr_subprocess *r;
58
59 STARTUPINFO si;
60 PROCESS_INFORMATION pi;
61
Nicolas "Pixel" Noble09ac0a42016-01-31 09:24:11 +010062 char *args = gpr_strjoin_sep(argv, (size_t)argc, " ", NULL);
Nicolas "Pixel" Noble4fba2862016-01-31 07:00:53 +010063 TCHAR *args_tchar;
64
65 args_tchar = gpr_char_to_tchar(args);
66 gpr_free(args);
67
68 memset(&si, 0, sizeof(si));
69 si.cb = sizeof(si);
70 memset(&pi, 0, sizeof(pi));
71
72 if (!CreateProcess(NULL, args_tchar, NULL, NULL, FALSE,
73 CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)) {
74 gpr_free(args_tchar);
75 return NULL;
76 }
77 gpr_free(args_tchar);
78
79 r = gpr_malloc(sizeof(gpr_subprocess));
80 memset(r, 0, sizeof(*r));
81 r->pi = pi;
82 return r;
83}
84
85void gpr_subprocess_destroy(gpr_subprocess *p) {
86 if (p) {
87 if (!p->joined) {
88 gpr_subprocess_interrupt(p);
89 gpr_subprocess_join(p);
90 }
91 if (p->pi.hProcess) {
92 CloseHandle(p->pi.hProcess);
93 }
94 if (p->pi.hThread) {
95 CloseHandle(p->pi.hThread);
96 }
97 gpr_free(p);
98 }
99}
100
101int gpr_subprocess_join(gpr_subprocess *p) {
102 DWORD dwExitCode;
103 if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
104 if (dwExitCode == STILL_ACTIVE) {
105 if (WaitForSingleObject(p->pi.hProcess, INFINITE) == WAIT_OBJECT_0) {
106 p->joined = 1;
107 goto getExitCode;
108 }
109 return -1; // failed to join
110 } else {
111 goto getExitCode;
112 }
113 } else {
114 return -1; // failed to get exit code
115 }
116
117getExitCode:
118 if (p->interrupted) {
119 return 0;
120 }
121 if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
Nicolas "Pixel" Noble09ac0a42016-01-31 09:24:11 +0100122 return (int)dwExitCode;
Nicolas "Pixel" Noble4fba2862016-01-31 07:00:53 +0100123 } else {
124 return -1; // failed to get exit code
125 }
126}
127
128void gpr_subprocess_interrupt(gpr_subprocess *p) {
129 DWORD dwExitCode;
130 if (GetExitCodeProcess(p->pi.hProcess, &dwExitCode)) {
131 if (dwExitCode == STILL_ACTIVE) {
132 gpr_log(GPR_INFO, "sending ctrl-break");
133 GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, p->pi.dwProcessId);
134 p->joined = 1;
135 p->interrupted = 1;
136 }
137 }
138 return;
139}
140
141#endif /* GPR_WINDOWS_SUBPROCESS */