libuv-svace-build
346 строк · 8.2 Кб
1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2*
3* Permission is hereby granted, free of charge, to any person obtaining a copy
4* of this software and associated documentation files (the "Software"), to
5* deal in the Software without restriction, including without limitation the
6* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7* sell copies of the Software, and to permit persons to whom the Software is
8* furnished to do so, subject to the following conditions:
9*
10* The above copyright notice and this permission notice shall be included in
11* all copies or substantial portions of the Software.
12*
13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19* IN THE SOFTWARE.
20*/
21
22#include <fcntl.h>23#include <io.h>24#include <malloc.h>25#include <stdio.h>26#include <process.h>27#if !defined(__MINGW32__)28# include <crtdbg.h>29#endif30
31
32#include "task.h"33#include "runner.h"34
35
36/*
37* Define the stuff that MinGW doesn't have
38*/
39#ifndef GetFileSizeEx40WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile,41PLARGE_INTEGER lpFileSize);42#endif43
44
45/* Do platform-specific initialization. */
46void platform_init(int argc, char **argv) {47/* Disable the "application crashed" popup. */48SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |49SEM_NOOPENFILEERRORBOX);50#if !defined(__MINGW32__)51_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);52_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);53#endif54
55_setmode(0, _O_BINARY);56_setmode(1, _O_BINARY);57_setmode(2, _O_BINARY);58
59#ifdef _MSC_VER60_set_fmode(_O_BINARY);61#else62_fmode = _O_BINARY;63#endif64
65/* Disable stdio output buffering. */66setvbuf(stdout, NULL, _IONBF, 0);67setvbuf(stderr, NULL, _IONBF, 0);68
69strcpy(executable_path, argv[0]);70}
71
72
73int process_start(char *name, char *part, process_info_t *p, int is_helper) {74HANDLE file = INVALID_HANDLE_VALUE;75HANDLE nul = INVALID_HANDLE_VALUE;76WCHAR path[MAX_PATH], filename[MAX_PATH];77WCHAR image[MAX_PATH + 1];78WCHAR args[MAX_PATH * 2];79STARTUPINFOW si;80PROCESS_INFORMATION pi;81DWORD result;82
83if (!is_helper) {84/* Give the helpers time to settle. Race-y, fix this. */85uv_sleep(250);86}87
88if (GetTempPathW(sizeof(path) / sizeof(WCHAR), (WCHAR*)&path) == 0)89goto error;90if (GetTempFileNameW((WCHAR*)&path, L"uv", 0, (WCHAR*)&filename) == 0)91goto error;92
93file = CreateFileW((WCHAR*)filename,94GENERIC_READ | GENERIC_WRITE,950,96NULL,97CREATE_ALWAYS,98FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,99NULL);100if (file == INVALID_HANDLE_VALUE)101goto error;102
103if (!SetHandleInformation(file, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))104goto error;105
106nul = CreateFileA("nul",107GENERIC_READ,108FILE_SHARE_READ | FILE_SHARE_WRITE,109NULL,110OPEN_EXISTING,111FILE_ATTRIBUTE_NORMAL,112NULL);113if (nul == INVALID_HANDLE_VALUE)114goto error;115
116if (!SetHandleInformation(nul, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))117goto error;118
119result = GetModuleFileNameW(NULL,120(WCHAR*) &image,121sizeof(image) / sizeof(WCHAR));122if (result == 0 || result == sizeof(image))123goto error;124
125if (part) {126if (_snwprintf((WCHAR*)args,127sizeof(args) / sizeof(WCHAR),128L"\"%s\" %S %S",129image,130name,131part) < 0) {132goto error;133}134} else {135if (_snwprintf((WCHAR*)args,136sizeof(args) / sizeof(WCHAR),137L"\"%s\" %S",138image,139name) < 0) {140goto error;141}142}143
144memset((void*)&si, 0, sizeof(si));145si.cb = sizeof(si);146si.dwFlags = STARTF_USESTDHANDLES;147si.hStdInput = nul;148si.hStdOutput = file;149si.hStdError = file;150
151if (!CreateProcessW(image, args, NULL, NULL, TRUE,1520, NULL, NULL, &si, &pi))153goto error;154
155CloseHandle(pi.hThread);156
157SetHandleInformation(nul, HANDLE_FLAG_INHERIT, 0);158SetHandleInformation(file, HANDLE_FLAG_INHERIT, 0);159
160p->stdio_in = nul;161p->stdio_out = file;162p->process = pi.hProcess;163p->name = part;164
165return 0;166
167error:168if (file != INVALID_HANDLE_VALUE)169CloseHandle(file);170if (nul != INVALID_HANDLE_VALUE)171CloseHandle(nul);172
173return -1;174}
175
176
177/* Timeout is in msecs. Set timeout < 0 to never time out. Returns 0 when all
178* processes are terminated, -2 on timeout. */
179int process_wait(process_info_t *vec, int n, int timeout) {180int i;181HANDLE handles[MAXIMUM_WAIT_OBJECTS];182DWORD timeout_api, result;183
184/* If there's nothing to wait for, return immediately. */185if (n == 0)186return 0;187
188ASSERT_LE(n, MAXIMUM_WAIT_OBJECTS);189
190for (i = 0; i < n; i++)191handles[i] = vec[i].process;192
193if (timeout >= 0) {194timeout_api = (DWORD)timeout;195} else {196timeout_api = INFINITE;197}198
199result = WaitForMultipleObjects(n, handles, TRUE, timeout_api);200
201if (result < WAIT_OBJECT_0 + n) {202/* All processes are terminated. */203return 0;204}205if (result == WAIT_TIMEOUT) {206return -2;207}208return -1;209}
210
211
212long int process_output_size(process_info_t *p) {213LARGE_INTEGER size;214if (!GetFileSizeEx(p->stdio_out, &size))215return -1;216return (long int)size.QuadPart;217}
218
219
220int process_copy_output(process_info_t* p, FILE* stream) {221char buf[1024];222int fd, r;223
224fd = _open_osfhandle((intptr_t)p->stdio_out, _O_RDONLY | _O_TEXT);225if (fd == -1)226return -1;227
228r = _lseek(fd, 0, SEEK_SET);229if (r < 0)230return -1;231
232while ((r = _read(fd, buf, sizeof(buf))) != 0)233print_lines(buf, r, stream);234
235_close(fd);236return 0;237}
238
239
240int process_read_last_line(process_info_t *p,241char * buffer,242size_t buffer_len) {243DWORD size;244DWORD read;245DWORD start;246OVERLAPPED overlapped;247
248ASSERT_GT(buffer_len, 0);249
250size = GetFileSize(p->stdio_out, NULL);251if (size == INVALID_FILE_SIZE)252return -1;253
254if (size == 0) {255buffer[0] = '\0';256return 1;257}258
259memset(&overlapped, 0, sizeof overlapped);260if (size >= buffer_len)261overlapped.Offset = size - buffer_len - 1;262
263if (!ReadFile(p->stdio_out, buffer, buffer_len - 1, &read, &overlapped))264return -1;265
266start = read;267while (start-- > 0) {268if (buffer[start] == '\n' || buffer[start] == '\r')269break;270}271
272if (start > 0)273memmove(buffer, buffer + start, read - start);274
275buffer[read - start] = '\0';276
277return 0;278}
279
280
281char* process_get_name(process_info_t *p) {282return p->name;283}
284
285
286int process_terminate(process_info_t *p) {287if (!TerminateProcess(p->process, 1))288return -1;289return 0;290}
291
292
293int process_reap(process_info_t *p) {294DWORD exitCode;295if (!GetExitCodeProcess(p->process, &exitCode))296return -1;297return (int)exitCode;298}
299
300
301void process_cleanup(process_info_t *p) {302CloseHandle(p->process);303CloseHandle(p->stdio_in);304}
305
306
307static int clear_line(void) {308HANDLE handle;309CONSOLE_SCREEN_BUFFER_INFO info;310COORD coord;311DWORD written;312
313handle = (HANDLE)_get_osfhandle(_fileno(stderr));314if (handle == INVALID_HANDLE_VALUE)315return -1;316
317if (!GetConsoleScreenBufferInfo(handle, &info))318return -1;319
320coord = info.dwCursorPosition;321if (coord.Y <= 0)322return -1;323
324coord.X = 0;325
326if (!SetConsoleCursorPosition(handle, coord))327return -1;328
329if (!FillConsoleOutputCharacterW(handle,3300x20,331info.dwSize.X,332coord,333&written)) {334return -1;335}336
337return 0;338}
339
340
341void rewind_cursor() {342if (clear_line() == -1) {343/* If clear_line fails (stdout is not a console), print a newline. */344fprintf(stderr, "\n");345}346}
347