Skip to content

Latest commit

 

History

History
1389 lines (1158 loc) · 39.5 KB

process.c

File metadata and controls

1389 lines (1158 loc) · 39.5 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
Jun 1, 2012
Jun 1, 2012
22
#include <assert.h>
May 28, 2012
May 28, 2012
23
#include <io.h>
Jul 30, 2011
Jul 30, 2011
24
25
#include <stdio.h>
#include <stdlib.h>
Nov 2, 2011
Nov 2, 2011
26
#include <signal.h>
Jun 2, 2012
Jun 2, 2012
27
28
29
30
#include "uv.h"
#include "internal.h"
#include "req-inl.h"
Jul 30, 2011
Jul 30, 2011
31
Jun 1, 2012
Jun 1, 2012
32
Nov 2, 2011
Nov 2, 2011
33
34
#define SIGKILL 9
Jun 1, 2012
Jun 1, 2012
35
36
37
38
39
40
41
42
43
44
45
46
/* CRT file descriptor mode flags */
#define FOPEN 0x01
#define FEOFLAG 0x02
#define FCRLF 0x04
#define FPIPE 0x08
#define FNOINHERIT 0x10
#define FAPPEND 0x20
#define FDEV 0x40
#define FTEXT 0x80
Aug 9, 2011
Aug 9, 2011
47
48
49
50
51
52
53
54
typedef struct env_var {
const char* narrow;
const wchar_t* wide;
int len; /* including null or '=' */
int supplied;
int value_len;
} env_var_t;
Aug 10, 2011
Aug 10, 2011
55
#define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
Aug 9, 2011
Aug 9, 2011
56
Jun 1, 2012
Jun 1, 2012
57
Jul 30, 2011
Jul 30, 2011
58
59
60
61
62
63
64
#define UTF8_TO_UTF16(s, t) \
size = uv_utf8_to_utf16(s, NULL, 0) * sizeof(wchar_t); \
t = (wchar_t*)malloc(size); \
if (!t) { \
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); \
} \
if (!uv_utf8_to_utf16(s, t, size / sizeof(wchar_t))) { \
Oct 6, 2011
Oct 6, 2011
65
uv__set_sys_error(loop, GetLastError()); \
Jul 30, 2011
Jul 30, 2011
66
67
68
69
70
err = -1; \
goto done; \
}
Jun 1, 2012
Jun 1, 2012
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* The `child_stdio_buffer` buffer has the following layout:
* int number_of_fds
* unsigned char crt_flags[number_of_fds]
* HANDLE os_handle[number_of_fds]
*/
#define CHILD_STDIO_SIZE(count) \
(sizeof(int) + \
sizeof(unsigned char) * (count) + \
sizeof(uintptr_t) * (count))
#define CHILD_STDIO_COUNT(buffer) \
*((unsigned int*) (buffer))
#define CHILD_STDIO_LPRESERVED2(buffer) \
((LPBYTE) (buffer))
#define CHILD_STDIO_CBRESERVED2(buffer) \
CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)))
#define CHILD_STDIO_CRT_FLAGS(buffer, fd) \
*((unsigned char*) (buffer) + sizeof(int) + fd)
#define CHILD_STDIO_HANDLE(buffer, fd) \
*((HANDLE*) ((unsigned char*) (buffer) + \
sizeof(int) + \
sizeof(unsigned char) * \
CHILD_STDIO_COUNT((buffer)) + \
sizeof(HANDLE) * (fd)))
Aug 31, 2011
Aug 31, 2011
102
static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
May 17, 2012
May 17, 2012
103
uv_handle_init(loop, (uv_handle_t*) handle);
Jul 30, 2011
Jul 30, 2011
104
105
106
107
108
109
110
handle->type = UV_PROCESS;
handle->exit_cb = NULL;
handle->pid = 0;
handle->exit_signal = 0;
handle->wait_handle = INVALID_HANDLE_VALUE;
handle->process_handle = INVALID_HANDLE_VALUE;
handle->close_handle = INVALID_HANDLE_VALUE;
Jun 1, 2012
Jun 1, 2012
111
handle->child_stdio_buffer = NULL;
Jul 30, 2011
Jul 30, 2011
112
Aug 31, 2011
Aug 31, 2011
113
uv_req_init(loop, (uv_req_t*)&handle->exit_req);
Jul 30, 2011
Jul 30, 2011
114
115
handle->exit_req.type = UV_PROCESS_EXIT;
handle->exit_req.data = handle;
Aug 31, 2011
Aug 31, 2011
116
uv_req_init(loop, (uv_req_t*)&handle->close_req);
Jul 30, 2011
Jul 30, 2011
117
118
119
handle->close_req.type = UV_PROCESS_CLOSE;
handle->close_req.data = handle;
Aug 31, 2011
Aug 31, 2011
120
121
loop->counters.handle_init++;
loop->counters.process_init++;
Jul 30, 2011
Jul 30, 2011
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
}
/*
* Path search functions
*/
/*
* Helper function for search_path
*/
static wchar_t* search_path_join_test(const wchar_t* dir,
int dir_len,
const wchar_t* name,
int name_len,
const wchar_t* ext,
int ext_len,
const wchar_t* cwd,
int cwd_len) {
wchar_t *result, *result_pos;
DWORD attrs;
if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {
/* It's a full path without drive letter, use cwd's drive letter only */
cwd_len = 2;
} else if (dir_len >= 2 && dir[1] == L':' &&
(dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) {
/* It's a relative path with drive letter (ext.g. D:../some/file)
* Replace drive letter in dir by full cwd if it points to the same drive,
* otherwise use the dir only.
*/
if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) {
cwd_len = 0;
} else {
dir += 2;
dir_len -= 2;
}
} else if (dir_len > 2 && dir[1] == L':') {
/* It's an absolute path with drive letter
* Don't use the cwd at all
*/
cwd_len = 0;
}
/* Allocate buffer for output */
Aug 31, 2011
Aug 31, 2011
166
167
result = result_pos = (wchar_t*)malloc(sizeof(wchar_t) *
(cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1));
Jul 30, 2011
Jul 30, 2011
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/* Copy cwd */
wcsncpy(result_pos, cwd, cwd_len);
result_pos += cwd_len;
/* Add a path separator if cwd didn't end with one */
if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
result_pos[0] = L'\\';
result_pos++;
}
/* Copy dir */
wcsncpy(result_pos, dir, dir_len);
result_pos += dir_len;
/* Add a separator if the dir didn't end with one */
if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
result_pos[0] = L'\\';
result_pos++;
}
/* Copy filename */
wcsncpy(result_pos, name, name_len);
result_pos += name_len;
if (ext_len) {
Aug 18, 2011
Aug 18, 2011
194
195
196
197
198
199
200
/* Add a dot if the filename didn't end with one */
if (name_len && result_pos[-1] != '.') {
result_pos[0] = L'.';
result_pos++;
}
/* Copy extension */
Jul 30, 2011
Jul 30, 2011
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
wcsncpy(result_pos, ext, ext_len);
result_pos += ext_len;
}
/* Null terminator */
result_pos[0] = L'\0';
attrs = GetFileAttributesW(result);
if (attrs != INVALID_FILE_ATTRIBUTES &&
!(attrs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))) {
return result;
}
free(result);
return NULL;
}
/*
* Helper function for search_path
*/
static wchar_t* path_search_walk_ext(const wchar_t *dir,
int dir_len,
const wchar_t *name,
int name_len,
wchar_t *cwd,
int cwd_len,
int name_has_ext) {
Aug 18, 2011
Aug 18, 2011
230
wchar_t* result;
Jul 30, 2011
Jul 30, 2011
231
Aug 18, 2011
Aug 18, 2011
232
/* If the name itself has a nonempty extension, try this extension first */
Jul 30, 2011
Jul 30, 2011
233
234
235
236
237
if (name_has_ext) {
result = search_path_join_test(dir, dir_len,
name, name_len,
L"", 0,
cwd, cwd_len);
Aug 18, 2011
Aug 18, 2011
238
239
if (result != NULL) {
return result;
Jul 30, 2011
Jul 30, 2011
240
}
Aug 18, 2011
Aug 18, 2011
241
}
Jul 30, 2011
Jul 30, 2011
242
Aug 18, 2011
Aug 18, 2011
243
244
245
246
247
248
249
250
/* Try .com extension */
result = search_path_join_test(dir, dir_len,
name, name_len,
L"com", 3,
cwd, cwd_len);
if (result != NULL) {
return result;
}
Jul 30, 2011
Jul 30, 2011
251
Aug 18, 2011
Aug 18, 2011
252
253
254
255
256
257
258
/* Try .exe extension */
result = search_path_join_test(dir, dir_len,
name, name_len,
L"exe", 3,
cwd, cwd_len);
if (result != NULL) {
return result;
Jul 30, 2011
Jul 30, 2011
259
260
}
Aug 18, 2011
Aug 18, 2011
261
return NULL;
Jul 30, 2011
Jul 30, 2011
262
263
264
265
266
267
268
269
270
271
}
/*
* search_path searches the system path for an executable filename -
* the windows API doesn't provide this as a standalone function nor as an
* option to CreateProcess.
*
* It tries to return an absolute filename.
*
Aug 18, 2011
Aug 18, 2011
272
273
274
275
* Furthermore, it tries to follow the semantics that cmd.exe, with this
* exception that PATHEXT environment variable isn't used. Since CreateProcess
* can start only .com and .exe files, only those extensions are tried. This
* behavior equals that of msvcrt's spawn functions.
Jul 30, 2011
Jul 30, 2011
276
277
278
279
280
281
282
*
* - Do not search the path if the filename already contains a path (either
* relative or absolute).
*
* - If there's really only a filename, check the current directory for file,
* then search all path directories.
*
Aug 18, 2011
Aug 18, 2011
283
* - If filename specified has *any* extension, search for the file with the
Jul 30, 2011
Jul 30, 2011
284
285
286
* specified extension first.
*
* - If the literal filename is not found in a directory, try *appending*
Aug 18, 2011
Aug 18, 2011
287
* (not replacing) .com first and then .exe.
Jul 30, 2011
Jul 30, 2011
288
289
290
291
292
293
294
295
296
*
* - The path variable may contain relative paths; relative paths are relative
* to the cwd.
*
* - Directories in path may or may not end with a trailing backslash.
*
* - CMD does not trim leading/trailing whitespace from path/pathex entries
* nor from the environment variables as a whole.
*
Nov 30, 2011
Nov 30, 2011
297
* - When cmd.exe cannot read a directory, it will just skip it and go on
Jul 30, 2011
Jul 30, 2011
298
299
300
301
302
303
304
305
* searching. However, unlike posix-y systems, it will happily try to run a
* file that is not readable/executable; if the spawn fails it will not
* continue searching.
*
* TODO: correctly interpret UNC paths
*/
static wchar_t* search_path(const wchar_t *file,
wchar_t *cwd,
Aug 18, 2011
Aug 18, 2011
306
const wchar_t *path) {
Jul 30, 2011
Jul 30, 2011
307
308
309
310
int file_has_dir;
wchar_t* result = NULL;
wchar_t *file_name_start;
wchar_t *dot;
Nov 4, 2011
Nov 4, 2011
311
312
const wchar_t *dir_start, *dir_end, *dir_path;
int dir_len;
Jul 30, 2011
Jul 30, 2011
313
314
315
316
317
318
319
320
321
322
323
324
325
int name_has_ext;
int file_len = wcslen(file);
int cwd_len = wcslen(cwd);
/* If the caller supplies an empty filename,
* we're not gonna return c:\windows\.exe -- GFY!
*/
if (file_len == 0
|| (file_len == 1 && file[0] == L'.')) {
return NULL;
}
Aug 31, 2011
Aug 31, 2011
326
327
/* Find the start of the filename so we can split the directory from the */
/* name. */
Jul 30, 2011
Jul 30, 2011
328
329
330
331
332
333
334
335
336
337
338
339
340
341
for (file_name_start = (wchar_t*)file + file_len;
file_name_start > file
&& file_name_start[-1] != L'\\'
&& file_name_start[-1] != L'/'
&& file_name_start[-1] != L':';
file_name_start--);
file_has_dir = file_name_start != file;
/* Check if the filename includes an extension */
dot = wcschr(file_name_start, L'.');
name_has_ext = (dot != NULL && dot[1] != L'\0');
if (file_has_dir) {
Aug 18, 2011
Aug 18, 2011
342
/* The file has a path inside, don't use path */
Jul 30, 2011
Jul 30, 2011
343
344
345
346
result = path_search_walk_ext(
file, file_name_start - file,
file_name_start, file_len - (file_name_start - file),
cwd, cwd_len,
Aug 18, 2011
Aug 18, 2011
347
name_has_ext);
Jul 30, 2011
Jul 30, 2011
348
349
} else {
Nov 4, 2011
Nov 4, 2011
350
dir_end = path;
Jul 30, 2011
Jul 30, 2011
351
352
353
354
355
/* The file is really only a name; look in cwd first, then scan path */
result = path_search_walk_ext(L"", 0,
file, file_len,
cwd, cwd_len,
Aug 18, 2011
Aug 18, 2011
356
name_has_ext);
Jul 30, 2011
Jul 30, 2011
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
while (result == NULL) {
if (*dir_end == L'\0') {
break;
}
/* Skip the separator that dir_end now points to */
if (dir_end != path) {
dir_end++;
}
/* Next slice starts just after where the previous one ended */
dir_start = dir_end;
/* Slice until the next ; or \0 is found */
dir_end = wcschr(dir_start, L';');
if (dir_end == NULL) {
dir_end = wcschr(dir_start, L'\0');
}
/* If the slice is zero-length, don't bother */
if (dir_end - dir_start == 0) {
continue;
}
Nov 4, 2011
Nov 4, 2011
382
383
384
385
386
387
388
389
390
391
392
393
394
395
dir_path = dir_start;
dir_len = dir_end - dir_start;
/* Adjust if the path is quoted. */
if (dir_path[0] == '"' || dir_path[0] == '\'') {
++dir_path;
--dir_len;
}
if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') {
--dir_len;
}
result = path_search_walk_ext(dir_path, dir_len,
Jul 30, 2011
Jul 30, 2011
396
397
file, file_len,
cwd, cwd_len,
Aug 18, 2011
Aug 18, 2011
398
name_has_ext);
Jul 30, 2011
Jul 30, 2011
399
400
401
402
403
404
}
}
return result;
}
Aug 9, 2011
Aug 9, 2011
405
Aug 5, 2011
Aug 5, 2011
406
407
408
409
410
411
412
413
414
/*
* Quotes command line arguments
* Returns a pointer to the end (next char to be written) of the buffer
*/
wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
int len = wcslen(source),
i, quote_hit;
wchar_t* start;
Aug 18, 2011
Aug 18, 2011
415
/*
Aug 5, 2011
Aug 5, 2011
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
* Check if the string must be quoted;
* if unnecessary, don't do it, it may only confuse older programs.
*/
if (len == 0) {
return target;
}
if (NULL == wcspbrk(source, L" \t\"")) {
/* No quotation needed */
wcsncpy(target, source, len);
target += len;
return target;
}
if (NULL == wcspbrk(source, L"\"\\")) {
Aug 18, 2011
Aug 18, 2011
431
/*
Aug 5, 2011
Aug 5, 2011
432
433
434
435
436
437
438
439
440
441
442
* No embedded double quotes or backlashes, so I can just wrap
* quote marks around the whole thing.
*/
*(target++) = L'"';
wcsncpy(target, source, len);
target += len;
*(target++) = L'"';
return target;
}
/*
Nov 30, 2011
Nov 30, 2011
443
* Expected input/output:
Aug 5, 2011
Aug 5, 2011
444
445
446
447
448
* input : hello"world
* output: "hello\"world"
* input : hello""world
* output: "hello\"\"world"
* input : hello\world
Aug 5, 2011
Aug 5, 2011
449
* output: hello\world
Aug 5, 2011
Aug 5, 2011
450
* input : hello\\world
Aug 5, 2011
Aug 5, 2011
451
* output: hello\\world
Aug 5, 2011
Aug 5, 2011
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
* input : hello\"world
* output: "hello\\\"world"
* input : hello\\"world
* output: "hello\\\\\"world"
* input : hello world\
* output: "hello world\"
*/
*(target++) = L'"';
start = target;
quote_hit = 1;
for (i = len; i > 0; --i) {
*(target++) = source[i - 1];
if (quote_hit && source[i - 1] == L'\\') {
*(target++) = L'\\';
} else if(source[i - 1] == L'"') {
quote_hit = 1;
*(target++) = L'\\';
} else {
quote_hit = 0;
}
}
target[0] = L'\0';
wcsrev(start);
*(target++) = L'"';
return target;
}
Jul 30, 2011
Jul 30, 2011
481
Aug 9, 2011
Aug 9, 2011
482
Aug 5, 2011
Aug 5, 2011
483
wchar_t* make_program_args(char** args, int verbatim_arguments) {
Jul 30, 2011
Jul 30, 2011
484
485
486
487
488
489
wchar_t* dst;
wchar_t* ptr;
char** arg;
size_t size = 0;
size_t len;
int arg_count = 0;
Aug 1, 2011
Aug 1, 2011
490
491
492
wchar_t* buffer;
int arg_size;
int buffer_size = 0;
Jul 30, 2011
Jul 30, 2011
493
494
495
/* Count the required size. */
for (arg = args; *arg; arg++) {
Aug 1, 2011
Aug 1, 2011
496
497
498
arg_size = uv_utf8_to_utf16(*arg, NULL, 0) * sizeof(wchar_t);
size += arg_size;
buffer_size = arg_size > buffer_size ? arg_size : buffer_size;
Jul 30, 2011
Jul 30, 2011
499
500
501
arg_count++;
}
Aug 18, 2011
Aug 18, 2011
502
/* Adjust for potential quotes. Also assume the worst-case scenario
Aug 3, 2011
Aug 3, 2011
503
504
/* that every character needs escaping, so we need twice as much space. */
size = size * 2 + arg_count * 2;
Jul 30, 2011
Jul 30, 2011
505
506
507
508
509
510
dst = (wchar_t*)malloc(size);
if (!dst) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
Aug 1, 2011
Aug 1, 2011
511
512
513
514
515
buffer = (wchar_t*)malloc(buffer_size);
if (!buffer) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
Jul 30, 2011
Jul 30, 2011
516
ptr = dst;
Aug 1, 2011
Aug 1, 2011
517
518
for (arg = args; *arg; arg++) {
len = uv_utf8_to_utf16(*arg, buffer, (size_t)(size - (ptr - dst)));
Jul 30, 2011
Jul 30, 2011
519
if (!len) {
Aug 1, 2011
Aug 1, 2011
520
goto error;
Jul 30, 2011
Jul 30, 2011
521
}
Aug 5, 2011
Aug 5, 2011
522
523
524
525
526
527
528
if (verbatim_arguments) {
wcscpy(ptr, buffer);
ptr += len - 1;
} else {
ptr = quote_cmd_arg(buffer, ptr);
}
*ptr++ = *(arg + 1) ? L' ' : L'\0';
Jul 30, 2011
Jul 30, 2011
529
530
}
Aug 1, 2011
Aug 1, 2011
531
free(buffer);
Jul 30, 2011
Jul 30, 2011
532
return dst;
Aug 1, 2011
Aug 1, 2011
533
534
535
536
537
error:
free(dst);
free(buffer);
return NULL;
Jul 30, 2011
Jul 30, 2011
538
539
}
Aug 9, 2011
Aug 9, 2011
540
541
542
543
544
/*
* If we learn that people are passing in huge environment blocks
* then we should probably qsort() the array and then bsearch()
* to see if it contains this variable. But there are ownership
Aug 18, 2011
Aug 18, 2011
545
* issues associated with that solution; this is the caller's
Aug 9, 2011
Aug 9, 2011
546
547
* char**, and modifying it is rude.
*/
Aug 31, 2011
Aug 31, 2011
548
549
static void check_required_vars_contains_var(env_var_t* required, int size,
const char* var) {
Aug 9, 2011
Aug 9, 2011
550
551
552
553
554
555
556
557
558
559
int i;
for (i = 0; i < size; ++i) {
if (_strnicmp(required[i].narrow, var, required[i].len) == 0) {
required[i].supplied = 1;
return;
}
}
}
Jul 30, 2011
Jul 30, 2011
560
/*
Aug 9, 2011
Aug 9, 2011
561
562
563
* The way windows takes environment variables is different than what C does;
* Windows wants a contiguous block of null-terminated strings, terminated
* with an additional null.
Aug 18, 2011
Aug 18, 2011
564
*
Aug 9, 2011
Aug 9, 2011
565
566
567
568
569
570
* Windows has a few "essential" environment variables. winsock will fail
* to initialize if SYSTEMROOT is not defined; some APIs make reference to
* TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that
* these get defined if the input environment block does not contain any
* values for them.
*/
Aug 1, 2011
Aug 1, 2011
571
wchar_t* make_program_env(char** env_block) {
Jul 30, 2011
Jul 30, 2011
572
573
574
575
576
wchar_t* dst;
wchar_t* ptr;
char** env;
int env_len = 1 * sizeof(wchar_t); /* room for closing null */
int len;
Aug 9, 2011
Aug 9, 2011
577
578
579
580
581
582
583
584
int i;
DWORD var_size;
env_var_t required_vars[] = {
E_V("SYSTEMROOT"),
E_V("SYSTEMDRIVE"),
E_V("TEMP"),
};
Jul 30, 2011
Jul 30, 2011
585
586
for (env = env_block; *env; env++) {
Aug 31, 2011
Aug 31, 2011
587
check_required_vars_contains_var(required_vars,
Jan 18, 2012
Jan 18, 2012
588
ARRAY_SIZE(required_vars),
Aug 31, 2011
Aug 31, 2011
589
*env);
Jul 30, 2011
Jul 30, 2011
590
591
592
env_len += (uv_utf8_to_utf16(*env, NULL, 0) * sizeof(wchar_t));
}
Jan 18, 2012
Jan 18, 2012
593
for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
Aug 9, 2011
Aug 9, 2011
594
595
596
597
598
599
600
601
602
603
604
605
if (!required_vars[i].supplied) {
env_len += required_vars[i].len * sizeof(wchar_t);
var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
if (var_size == 0) {
uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
}
required_vars[i].value_len = (int)var_size;
env_len += (int)var_size * sizeof(wchar_t);
}
}
dst = malloc(env_len);
Jul 30, 2011
Jul 30, 2011
606
607
608
609
610
611
612
613
614
615
616
617
618
619
if (!dst) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
ptr = dst;
for (env = env_block; *env; env++, ptr += len) {
len = uv_utf8_to_utf16(*env, ptr, (size_t)(env_len - (ptr - dst)));
if (!len) {
free(dst);
return NULL;
}
}
Jan 18, 2012
Jan 18, 2012
620
for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
Aug 9, 2011
Aug 9, 2011
621
622
623
624
if (!required_vars[i].supplied) {
wcscpy(ptr, required_vars[i].wide);
ptr += required_vars[i].len - 1;
*ptr++ = L'=';
Aug 31, 2011
Aug 31, 2011
625
626
627
var_size = GetEnvironmentVariableW(required_vars[i].wide,
ptr,
required_vars[i].value_len);
Aug 9, 2011
Aug 9, 2011
628
629
630
631
632
633
634
if (var_size == 0) {
uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
}
ptr += required_vars[i].value_len;
}
}
Jul 30, 2011
Jul 30, 2011
635
636
637
638
639
*ptr = L'\0';
return dst;
}
Jun 1, 2012
Jun 1, 2012
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
static int uv_create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* server_pipe,
HANDLE* child_pipe_ptr, unsigned int flags) {
char pipe_name[64];
SECURITY_ATTRIBUTES sa;
DWORD server_access = 0;
DWORD client_access = 0;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
if (flags & UV_READABLE_PIPE) {
server_access |= PIPE_ACCESS_OUTBOUND;
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
}
if (flags & UV_WRITABLE_PIPE) {
server_access |= PIPE_ACCESS_INBOUND;
client_access |= GENERIC_WRITE;
}
/* Create server pipe handle. */
if (uv_stdio_pipe_server(loop,
server_pipe,
server_access,
pipe_name,
sizeof(pipe_name)) < 0) {
goto error;
}
/* Create child pipe handle. */
sa.nLength = sizeof sa;
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
child_pipe = CreateFileA(pipe_name,
client_access,
0,
&sa,
OPEN_EXISTING,
server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if (child_pipe == INVALID_HANDLE_VALUE) {
uv__set_sys_error(loop, GetLastError());
goto error;
}
#ifndef NDEBUG
/* Validate that the pipe was opened in the right mode. */
{
DWORD mode;
BOOL r = GetNamedPipeHandleState(child_pipe,
&mode,
NULL,
NULL,
NULL,
NULL,
0);
assert(r == TRUE);
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
}
#endif
/* Do a blocking ConnectNamedPipe. This should not block because we have */
/* both ends of the pipe created. */
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
uv__set_sys_error(loop, GetLastError());
goto error;
}
}
*child_pipe_ptr = child_pipe;
return 0;
error:
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
uv_pipe_cleanup(loop, server_pipe);
}
if (child_pipe != INVALID_HANDLE_VALUE) {
CloseHandle(child_pipe);
}
return -1;
}
static int duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
HANDLE current_process;
current_process = GetCurrentProcess();
if (!DuplicateHandle(current_process,
handle,
current_process,
dup,
0,
TRUE,
DUPLICATE_SAME_ACCESS)) {
*dup = INVALID_HANDLE_VALUE;
uv__set_sys_error(loop, GetLastError());
return -1;
}
return 0;
}
static int duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
HANDLE handle;
if (fd == -1) {
*dup = INVALID_HANDLE_VALUE;
uv__set_artificial_error(loop, UV_EBADF);
return -1;
}
handle = (HANDLE)_get_osfhandle(fd);
return duplicate_handle(loop, handle, dup);
}
Jun 2, 2012
Jun 2, 2012
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
static int create_nul_handle(uv_loop_t* loop, HANDLE* handle_ptr,
DWORD access) {
HANDLE handle;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof sa;
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
handle = CreateFileW(L"NUL",
access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
&sa,
OPEN_EXISTING,
0,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
uv__set_sys_error(loop, GetLastError());
return -1;
}
*handle_ptr = handle;
return 0;
}
Jun 1, 2012
Jun 1, 2012
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
static void set_child_stdio_noinherit(void* buffer) {
int i, count;
count = CHILD_STDIO_COUNT(buffer);
for (i = 0; i < count; i++) {
HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
if (handle != INVALID_HANDLE_VALUE) {
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
}
}
}
static void close_and_free_child_stdio(void* buffer) {
int i, count;
count = CHILD_STDIO_COUNT(buffer);
for (i = 0; i < count; i++) {
HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
if (handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle);
}
}
free(buffer);
}
Aug 2, 2011
Aug 2, 2011
813
814
815
/*
* Called on Windows thread-pool thread to indicate that
* a child process has exited.
Jul 30, 2011
Jul 30, 2011
816
817
818
*/
static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
uv_process_t* process = (uv_process_t*)data;
Aug 31, 2011
Aug 31, 2011
819
uv_loop_t* loop = process->loop;
Aug 2, 2011
Aug 2, 2011
820
Jul 30, 2011
Jul 30, 2011
821
822
assert(didTimeout == FALSE);
assert(process);
Aug 2, 2011
Aug 2, 2011
823
Jul 30, 2011
Jul 30, 2011
824
/* Post completed */
Aug 31, 2011
Aug 31, 2011
825
POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
Jul 30, 2011
Jul 30, 2011
826
827
828
}
Aug 2, 2011
Aug 2, 2011
829
830
831
/*
* Called on Windows thread-pool thread to indicate that
* UnregisterWaitEx has completed.
Jul 30, 2011
Jul 30, 2011
832
833
834
*/
static void CALLBACK close_wait_callback(void* data, BOOLEAN didTimeout) {
uv_process_t* process = (uv_process_t*)data;
Aug 31, 2011
Aug 31, 2011
835
uv_loop_t* loop = process->loop;
Aug 2, 2011
Aug 2, 2011
836
Jul 30, 2011
Jul 30, 2011
837
838
839
840
assert(didTimeout == FALSE);
assert(process);
/* Post completed */
Aug 31, 2011
Aug 31, 2011
841
POST_COMPLETION_FOR_REQ(loop, &process->close_req);
Jul 30, 2011
Jul 30, 2011
842
843
844
}
Aug 2, 2011
Aug 2, 2011
845
846
847
848
849
850
851
852
853
/*
* Called on windows thread pool when CreateProcess failed. It writes an error
* message to the process' intended stderr and then posts a PROCESS_EXIT
* packet to the completion port.
*/
static DWORD WINAPI spawn_failure(void* data) {
char syscall[] = "CreateProcessW: ";
char unknown[] = "unknown error\n";
uv_process_t* process = (uv_process_t*) data;
Aug 31, 2011
Aug 31, 2011
854
uv_loop_t* loop = process->loop;
Jun 1, 2012
Jun 1, 2012
855
HANDLE child_stderr = CHILD_STDIO_HANDLE(process->child_stdio_buffer, 2);
Aug 2, 2011
Aug 2, 2011
856
857
858
char* buf = NULL;
DWORD count, written;
May 28, 2012
May 28, 2012
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
if (child_stderr != INVALID_HANDLE_VALUE) {
WriteFile(child_stderr, syscall, sizeof(syscall) - 1, &written, NULL);
count = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
process->spawn_errno,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buf,
0,
NULL);
if (buf != NULL && count > 0) {
WriteFile(child_stderr, buf, count, &written, NULL);
LocalFree(buf);
} else {
WriteFile(child_stderr, unknown, sizeof(unknown) - 1, &written, NULL);
}
Aug 2, 2011
Aug 2, 2011
878
May 28, 2012
May 28, 2012
879
880
FlushFileBuffers(child_stderr);
}
Aug 2, 2011
Aug 2, 2011
881
882
/* Post completed */
Aug 31, 2011
Aug 31, 2011
883
POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
Aug 2, 2011
Aug 2, 2011
884
885
886
887
888
return 0;
}
Sep 6, 2011
Sep 6, 2011
889
890
891
/* Called on main thread after a child process has exited. */
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
DWORD exit_code;
Jul 30, 2011
Jul 30, 2011
892
May 17, 2012
May 17, 2012
893
894
895
896
897
/* FIXME: race condition. */
if (handle->flags & UV_HANDLE_CLOSING) {
return;
}
Jul 30, 2011
Jul 30, 2011
898
899
900
901
902
903
/* Unregister from process notification. */
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(handle->wait_handle);
handle->wait_handle = INVALID_HANDLE_VALUE;
}
May 17, 2012
May 17, 2012
904
905
906
907
if (handle->process_handle == INVALID_HANDLE_VALUE ||
!GetExitCodeProcess(handle->process_handle, &exit_code)) {
/* The process never even started in the first place, or we were unable */
/* to obtain the exit code. */
Aug 2, 2011
Aug 2, 2011
908
exit_code = 127;
Jul 30, 2011
Jul 30, 2011
909
910
}
May 17, 2012
May 17, 2012
911
912
913
914
/* Set the handle to inactive: no callbacks will be made after the exit */
/* callback.*/
uv__handle_stop(handle);
Jul 30, 2011
Jul 30, 2011
915
916
917
918
919
920
921
922
/* Fire the exit callback. */
if (handle->exit_cb) {
handle->exit_cb(handle, exit_code, handle->exit_signal);
}
}
/* Called on main thread after UnregisterWaitEx finishes. */
Aug 31, 2011
Aug 31, 2011
923
924
void uv_process_proc_close(uv_loop_t* loop, uv_process_t* handle) {
uv_want_endgame(loop, (uv_handle_t*)handle);
Jul 30, 2011
Jul 30, 2011
925
926
927
}
Aug 31, 2011
Aug 31, 2011
928
void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
May 17, 2012
May 17, 2012
929
930
uv__handle_start(handle);
Jul 30, 2011
Jul 30, 2011
931
932
933
934
935
936
937
938
939
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
handle->close_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
UnregisterWaitEx(handle->wait_handle, handle->close_handle);
handle->wait_handle = NULL;
RegisterWaitForSingleObject(&handle->wait_handle, handle->close_handle,
close_wait_callback, (void*)handle, INFINITE,
WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
} else {
Aug 31, 2011
Aug 31, 2011
940
uv_want_endgame(loop, (uv_handle_t*)handle);
Jul 30, 2011
Jul 30, 2011
941
942
943
944
}
}
May 17, 2012
May 17, 2012
945
946
947
948
949
950
951
952
953
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
if (handle->flags & UV_HANDLE_CLOSING) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
uv__handle_stop(handle);
/* Clean-up the process handle. */
CloseHandle(handle->process_handle);
/* Clean up the child stdio ends that may have been left open. */
Jun 1, 2012
Jun 1, 2012
954
955
956
957
if (handle->child_stdio_buffer != NULL) {
close_and_free_child_stdio(handle->child_stdio_buffer);
}
May 30, 2012
May 30, 2012
958
uv__handle_close(handle);
May 17, 2012
May 17, 2012
959
960
961
962
}
}
Jun 1, 2012
Jun 1, 2012
963
964
965
966
static int init_child_stdio(uv_loop_t* loop, uv_process_options_t* options,
void** buffer_ptr) {
void* buffer;
int count, i;
Jul 30, 2011
Jul 30, 2011
967
Jun 1, 2012
Jun 1, 2012
968
count = options->stdio_count;
Jul 30, 2011
Jul 30, 2011
969
Jun 1, 2012
Jun 1, 2012
970
971
972
973
974
975
976
if (count < 0 || count > 255) {
/* Only support FDs 0-255 */
uv__set_artificial_error(loop, UV_ENOTSUP);
return -1;
} else if (count < 3) {
/* There should always be at least 3 stdio handles. */
count = 3;
Jul 30, 2011
Jul 30, 2011
977
978
}
Jun 1, 2012
Jun 1, 2012
979
980
981
982
983
/* Allocate the child stdio buffer */
buffer = malloc(CHILD_STDIO_SIZE(count));
if (buffer == NULL) {
uv__set_artificial_error(loop, UV_ENOMEM);
return -1;
Jul 30, 2011
Jul 30, 2011
984
985
}
Jun 1, 2012
Jun 1, 2012
986
987
988
989
990
991
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
/* clean up on failure. */
CHILD_STDIO_COUNT(buffer) = count;
for (i = 0; i < count; i++) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
Jul 30, 2011
Jul 30, 2011
992
993
}
Jun 2, 2012
Jun 2, 2012
994
995
996
997
998
999
1000
for (i = 0; i < count; i++) {
uv_stdio_container_t fdopt;
if (i < options->stdio_count) {
fdopt = options->stdio[i];
} else {
fdopt.flags = UV_IGNORE;
}