Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: src/trusted/platform/win/nacl_process.c

Issue 10832400: Process abstraction layer for NaCl Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Provide consistent interface across all platforms. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include "native_client/src/trusted/platform/nacl_process.h"
8
9 #include <fcntl.h>
10 #include <io.h>
11 #include <windows.h>
12 #include <userenv.h>
13 #include <psapi.h>
14
15 #include "native_client/src/include/portability.h"
16 #include "native_client/src/include/portability_string.h"
17
18 #include "native_client/src/shared/platform/nacl_check.h"
19 #include "native_client/src/shared/platform/nacl_log.h"
20 #include "native_client/src/shared/platform/nacl_sync.h"
21 #include "native_client/src/shared/platform/nacl_sync_checked.h"
22
23 #ifndef STATUS_SUCCESS
Mark Seaborn 2012/08/24 00:22:42 Aren't these defined by the Windows headers? If s
24 #define STATUS_SUCCESS ((NTSTATUS) 0)
25 #endif
26 #ifndef STATUS_WAIT_1
27 #define STATUS_WAIT_1 ((NTSTATUS) 0x00000001)
28 #endif
29 #ifndef STATUS_DEBUGGER_INACTIVE
30 #define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354)
31 #endif
32 #ifndef STATUS_CONTROL_C_EXIT
33 #define STATUS_CONTROL_C_EXIT ((NTSTATUS) 0xC000013A)
34 #endif
35 #ifndef DBG_TERMINATE_PROCESS
36 #define DBG_TERMINATE_PROCESS ((NTSTATUS) 0x40010004)
37 #endif
38
39 static char *NaClEscapeShellArg(const char *str) {
Mark Seaborn 2012/08/24 00:22:42 I don't know whether this properly implements Wind
40 const char *p;
41 char *esc;
42 char *q;
43
44 esc = calloc(2 * strlen(str) + 1, sizeof *esc);
45 for (p = str, q = esc; 0 != *p; ++p) {
46 if (*p == '"') {
47 *q++ = '\\';
48 } else if (*p == '\\' && *(p + 1) == '"') {
49 *q++ = '\\';
50 }
51 *q++ = *p;
52 }
53
54 return esc;
55 }
56
57 int NaClProcessLaunch(struct NaClProcess *npp,
58 char *const *argv,
59 char *const *envp,
60 int flags) {
61 char cmd[MAX_PATH];
62 char const *const *p;
63 size_t off;
64 STARTUPINFO startup_info;
65 PROCESS_INFORMATION process_info;
66 DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT;
67 BOOL inherit;
68
69 NaClLog(2,
70 ("NaClProcessLaunch(0x%08"NACL_PRIxPTR", 0x%08"NACL_PRIxPTR
71 ", 0x%08"NACL_PRIxPTR", 0x%x)\n"),
72 (uintptr_t) npp, (uintptr_t) argv, (uintptr_t) envp, flags);
73
74 CHECK(npp != NULL);
75
76 ZeroMemory(&startup_info, sizeof startup_info);
Mark Seaborn 2012/08/24 00:22:42 Using memset() is more usual, since it's a better-
77 startup_info.cb = sizeof startup_info;
78 startup_info.dwFlags = STARTF_USESTDHANDLES;
79
80 /* Convert arguments to a single command string */
81 off = 0;
82 for (p = argv; NULL != *p; ++p) {
83 size_t len;
84 char *arg;
85 if (p != argv) {
86 cmd[off++] = ' ';
87 }
88 arg = NaClEscapeShellArg(*p);
89 len = _snprintf(cmd + off, MAX_PATH - off, "\"%s\"", arg);
90 free(arg);
91 if (MAX_PATH - off < len) {
92 break;
93 }
94 off += len;
95 }
96 cmd[off] = '\0';
97
98 if ((flags & NACL_PROCESS_LAUNCH_CLOSE_FDS) != 0) {
99 inherit = FALSE;
100 } else {
101 inherit = TRUE;
102 }
103
104 if (0 != (flags & NACL_PROCESS_LAUNCH_NEW_GROUP)) {
105 creation_flags |= CREATE_NEW_PROCESS_GROUP;
106 }
107
108 if (!CreateProcess(/* lpApplicationName= */ NULL,
109 cmd,
110 /* lpProcessAttributes= */ NULL,
111 /* lpThreadAttributes= */ NULL,
112 inherit,
113 creation_flags,
114 envp,
115 /* lpCurrentDirectory= */NULL,
116 &startup_info,
117 &process_info)) {
118 NaClLog(LOG_ERROR,
119 "NaClProcessSpawn: CreateProcess failed, error %d\n",
120 GetLastError());
121 return 0;
122 }
123
124 /* TODO(phosek): might we ever need this handle? */
125 DCHECK(CloseHandle(process_info.hThread));
126
127 if (npp != NULL) {
128 npp->handle = process_info.hProcess;
129 }
130
131 return 1;
132 }
133
134 int NaClProcessKill(struct NaClProcess *npp, int exit_code, int wait) {
135 BOOL retval;
136
137 NaClLog(2,
138 "NaClProcessKill(0x%08"NACL_PRIxPTR", %d, %d)\n",
139 (uintptr_t) npp, exit_code, wait);
140
141 CHECK(npp != NULL);
142
143 retval = TerminateProcess(npp->handle, exit_code);
144 if (FALSE == retval) {
145 NaClLog(LOG_ERROR,
146 "NaClProcessKill: unable to terminate process, error %d\n",
147 GetLastError());
148 goto done;
149 }
150
151 if (wait != 0) {
152 /* The process may not end immediately due to pending I/O */
153 if (WAIT_OBJECT_0 != WaitForSingleObject(npp->handle, 60 * 1000)) {
Mark Seaborn 2012/08/24 00:22:42 Why a hard-coded timeout? What is the use case?
154 NaClLog(LOG_ERROR,
155 "NaClProcessKill: waiting for process failed, error %d\n",
156 GetLastError());
157 }
158 }
159
160 done:
161 return retval != FALSE;
162 }
163
164 int NaClProcessGetStatus(
165 struct NaClProcess *npp,
166 int *status) {
167 DWORD exit_code = 0;
168
169 NaClLog(2,
170 ("NaClProcessGetStatus(0x%08"NACL_PRIxPTR
171 ", 0x%08"NACL_PRIxPTR")\n"),
172 (uintptr_t) npp, (uintptr_t) status);
173
174 CHECK(npp != NULL);
175
176 NaClLog(4,
177 "NaClProcessGetStatus: checking status of process %d\n",
178 (int) npp->handle);
179
180 if (!GetExitCodeProcess(npp->handle, &exit_code)) {
181 NaClLog(LOG_ERROR,
182 ("NaClProcessGetStatus: GetExitCodeProcess"
183 "returned error %d\n"),
184 GetLastError());
185 return 0;
186 }
187
188 if (STILL_ACTIVE == exit_code) {
189 DWORD wait_result = WaitForSingleObject(npp->handle, 0);
190 if (WAIT_TIMEOUT == wait_result) {
191 *status = NACL_PROCESS_STATUS_STILL_RUNNING;
192 return 1;
193 }
194
195 CHECK(WAIT_OBJECT_0 == wait_result);
196 /* The process used 0x103 (STILL_ACTIVE) as exit code. */
197 *status = NACL_PROCESS_STATUS_ABNORMAL_EXIT;
198 return 1;
199 }
200
201 switch (exit_code) {
202 case STATUS_SUCCESS: /* Normal termination */
203 *status = NACL_PROCESS_STATUS_NORMAL_EXIT;
204 break;
205 case STATUS_DEBUGGER_INACTIVE: /* Debugger inactive */
206 case STATUS_CONTROL_C_EXIT: /* Keyboard interrupt */
207 case DBG_TERMINATE_PROCESS: /* Debugger terminated */
208 case STATUS_WAIT_1: /* Task manager killed */
209 *status = NACL_PROCESS_STATUS_KILLED;
210 break;
211 default:
212 /* All other exit codes indicate crashes */
213 *status = NACL_PROCESS_STATUS_CRASHED;
214 break;
215 }
216
217 return 1;
218 }
219
220 int NaClProcessWaitForExitCode(struct NaClProcess *npp,
221 int *exit_code) {
222 DWORD tmp_exit_code;
223
224 NaClLog(2,
225 ("NaClProcessWaitForExitCode(0x%08"NACL_PRIxPTR
226 ", 0x%08"NACL_PRIxPTR")\n"),
227 (uintptr_t) npp, (uintptr_t) exit_code);
228
229 CHECK(npp != NULL);
230
231 if (WAIT_OBJECT_0 != WaitForSingleObject(npp->handle, INFINITE)) {
232 return 0;
233 }
234
235 if (!GetExitCodeProcess(npp->handle, &tmp_exit_code)) {
236 return 0;
237 }
238
239 *exit_code = tmp_exit_code;
240 return 1;
241 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698