PageRenderTime 48ms CodeModel.GetById 8ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/test/runner-win.c

http://github.com/joyent/libuv
C | 292 lines | 196 code | 64 blank | 32 comment | 48 complexity | 67dbce6c6d7c43b96ee223357ec57d5d MD5 | raw file
  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#endif
 30
 31
 32#include "task.h"
 33#include "runner.h"
 34
 35
 36/*
 37 * Define the stuff that MinGW doesn't have
 38 */
 39#ifndef GetFileSizeEx
 40  WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile,
 41                                       PLARGE_INTEGER lpFileSize);
 42#endif
 43
 44
 45/* Do platform-specific initialization. */
 46void platform_init(int argc, char **argv) {
 47  /* Disable the "application crashed" popup. */
 48  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
 49      SEM_NOOPENFILEERRORBOX);
 50#if !defined(__MINGW32__)
 51  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
 52  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
 53#endif
 54
 55  _setmode(0, _O_BINARY);
 56  _setmode(1, _O_BINARY);
 57  _setmode(2, _O_BINARY);
 58
 59  /* Disable stdio output buffering. */
 60  setvbuf(stdout, NULL, _IONBF, 0);
 61  setvbuf(stderr, NULL, _IONBF, 0);
 62
 63  strcpy(executable_path, argv[0]);
 64}
 65
 66
 67int process_start(char *name, char *part, process_info_t *p, int is_helper) {
 68  HANDLE file = INVALID_HANDLE_VALUE;
 69  HANDLE nul = INVALID_HANDLE_VALUE;
 70  WCHAR path[MAX_PATH], filename[MAX_PATH];
 71  WCHAR image[MAX_PATH + 1];
 72  WCHAR args[MAX_PATH * 2];
 73  STARTUPINFOW si;
 74  PROCESS_INFORMATION pi;
 75  DWORD result;
 76
 77  if (GetTempPathW(sizeof(path) / sizeof(WCHAR), (WCHAR*)&path) == 0)
 78    goto error;
 79  if (GetTempFileNameW((WCHAR*)&path, L"uv", 0, (WCHAR*)&filename) == 0)
 80    goto error;
 81
 82  file = CreateFileW((WCHAR*)filename,
 83                     GENERIC_READ | GENERIC_WRITE,
 84                     0,
 85                     NULL,
 86                     CREATE_ALWAYS,
 87                     FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
 88                     NULL);
 89  if (file == INVALID_HANDLE_VALUE)
 90    goto error;
 91
 92  if (!SetHandleInformation(file, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
 93    goto error;
 94
 95  nul = CreateFileA("nul",
 96                    GENERIC_READ,
 97                    FILE_SHARE_READ | FILE_SHARE_WRITE,
 98                    NULL,
 99                    OPEN_EXISTING,
100                    FILE_ATTRIBUTE_NORMAL,
101                    NULL);
102  if (nul == INVALID_HANDLE_VALUE)
103    goto error;
104
105  if (!SetHandleInformation(nul, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
106    goto error;
107
108  result = GetModuleFileNameW(NULL, (WCHAR*)&image, sizeof(image) / sizeof(WCHAR));
109  if (result == 0 || result == sizeof(image))
110    goto error;
111
112  if (part) {
113    if (_snwprintf((WCHAR*)args,
114                   sizeof(args) / sizeof(WCHAR),
115                   L"\"%s\" %S %S",
116                   image,
117                   name,
118                   part) < 0) {
119      goto error;
120    }
121  } else {
122    if (_snwprintf((WCHAR*)args,
123                   sizeof(args) / sizeof(WCHAR),
124                   L"\"%s\" %S",
125                   image,
126                   name) < 0) {
127      goto error;
128    }
129  }
130
131  memset((void*)&si, 0, sizeof(si));
132  si.cb = sizeof(si);
133  si.dwFlags = STARTF_USESTDHANDLES;
134  si.hStdInput = nul;
135  si.hStdOutput = file;
136  si.hStdError = file;
137
138  if (!CreateProcessW(image, args, NULL, NULL, TRUE,
139                      0, NULL, NULL, &si, &pi))
140    goto error;
141
142  CloseHandle(pi.hThread);
143
144  SetHandleInformation(nul, HANDLE_FLAG_INHERIT, 0);
145  SetHandleInformation(file, HANDLE_FLAG_INHERIT, 0);
146
147  p->stdio_in = nul;
148  p->stdio_out = file;
149  p->process = pi.hProcess;
150  p->name = part;
151
152  return 0;
153
154error:
155  if (file != INVALID_HANDLE_VALUE)
156    CloseHandle(file);
157  if (nul != INVALID_HANDLE_VALUE)
158    CloseHandle(nul);
159
160  return -1;
161}
162
163
164/* Timeout is is msecs. Set timeout < 0 to never time out. */
165/* Returns 0 when all processes are terminated, -2 on timeout. */
166int process_wait(process_info_t *vec, int n, int timeout) {
167  int i;
168  HANDLE handles[MAXIMUM_WAIT_OBJECTS];
169  DWORD timeout_api, result;
170
171  /* If there's nothing to wait for, return immediately. */
172  if (n == 0)
173    return 0;
174
175  ASSERT(n <= MAXIMUM_WAIT_OBJECTS);
176
177  for (i = 0; i < n; i++)
178    handles[i] = vec[i].process;
179
180  if (timeout >= 0) {
181    timeout_api = (DWORD)timeout;
182  } else {
183    timeout_api = INFINITE;
184  }
185
186  result = WaitForMultipleObjects(n, handles, TRUE, timeout_api);
187
188  if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + n) {
189    /* All processes are terminated. */
190    return 0;
191  }
192  if (result == WAIT_TIMEOUT) {
193    return -2;
194  }
195  return -1;
196}
197
198
199long int process_output_size(process_info_t *p) {
200  LARGE_INTEGER size;
201  if (!GetFileSizeEx(p->stdio_out, &size))
202    return -1;
203  return (long int)size.QuadPart;
204}
205
206
207int process_copy_output(process_info_t *p, int fd) {
208  DWORD read;
209  char buf[1024];
210
211  if (SetFilePointer(p->stdio_out, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
212    return -1;
213
214  while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) &&
215         read > 0)
216    write(fd, buf, read);
217
218  if (GetLastError() != ERROR_HANDLE_EOF)
219    return -1;
220
221  return 0;
222}
223
224
225char* process_get_name(process_info_t *p) {
226  return p->name;
227}
228
229
230int process_terminate(process_info_t *p) {
231  if (!TerminateProcess(p->process, 1))
232    return -1;
233  return 0;
234}
235
236
237int process_reap(process_info_t *p) {
238  DWORD exitCode;
239  if (!GetExitCodeProcess(p->process, &exitCode))
240    return -1;
241  return (int)exitCode;
242}
243
244
245void process_cleanup(process_info_t *p) {
246  CloseHandle(p->process);
247  CloseHandle(p->stdio_in);
248  CloseHandle(p->stdio_out);
249}
250
251
252static int clear_line() {
253  HANDLE handle;
254  CONSOLE_SCREEN_BUFFER_INFO info;
255  COORD coord;
256  DWORD written;
257
258  handle = (HANDLE)_get_osfhandle(fileno(stderr));
259  if (handle == INVALID_HANDLE_VALUE)
260    return -1;
261
262  if (!GetConsoleScreenBufferInfo(handle, &info))
263    return -1;
264
265  coord = info.dwCursorPosition;
266  if (coord.Y <= 0)
267    return -1;
268
269  coord.X = 0;
270
271  if (!SetConsoleCursorPosition(handle, coord))
272    return -1;
273
274  if (!FillConsoleOutputCharacterW(handle, 0x20, info.dwSize.X, coord, &written))
275    return -1;
276
277  return 0;
278}
279
280
281void rewind_cursor() {
282  if (clear_line() == -1) {
283    /* If clear_line fails (stdout is not a console), print a newline. */
284    fprintf(stderr, "\n");
285  }
286}
287
288
289/* Pause the calling thread for a number of milliseconds. */
290void uv_sleep(int msec) {
291  Sleep(msec);
292}