예제 #1
0
static int run_test(int inprocess) {
  uv_process_t process;
  uv_thread_t tid;
  int r;

  if (inprocess) {
    r = uv_thread_create(&tid, ipc_send_recv_helper_threadproc, (void *) 42);
    ASSERT(r == 0);

    uv_sleep(1000);

    r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1);
    ASSERT(r == 0);

    uv_pipe_connect(&ctx.connect_req, &ctx.channel, TEST_PIPENAME_3, connect_cb);
  } else {
    spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper");

    connect_cb(&ctx.connect_req, 0);
  }

  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  ASSERT(r == 0);

  ASSERT(recv_cb_count == 2);

  if (inprocess) {
    r = uv_thread_join(&tid);
    ASSERT(r == 0);
  }

  return 0;
}
예제 #2
0
파일: run-tests.c 프로젝트: Motrixi/node
static int maybe_run_test(int argc, char **argv) {
  if (strcmp(argv[1], "spawn_helper1") == 0) {
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper2") == 0) {
    printf("hello world\n");
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper3") == 0) {
    char buffer[256];
    fgets(buffer, sizeof(buffer) - 1, stdin);
    buffer[sizeof(buffer) - 1] = '\0';
    fputs(buffer, stdout);
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper4") == 0) {
    /* Never surrender, never return! */
    while (1) uv_sleep(10000);
  }

  return run_test(argv[1], TEST_TIMEOUT, 0);
}
예제 #3
0
static void async_cb(uv_async_t* handle) {
  if (++callbacks == NUM_PINGS) {
    /* Tell the pummel thread to stop. */
    ACCESS_ONCE(const char*, handle->data) = stop;

    /* Wait for for the pummel thread to acknowledge that it has stoppped. */
    while (ACCESS_ONCE(const char*, handle->data) != stopped)
      uv_sleep(0);

    uv_close((uv_handle_t*) handle, NULL);
  }
예제 #4
0
void StartServiceLoop(void *pVoid)
{
	XConfig::XLoopServiceInfo *pXLoopServiceInfo = (XConfig::XLoopServiceInfo *)pVoid;
	while (pXLoopServiceInfo->iStatus)
	{
		byte *pResponseBuffer = NULL;
		size_t szResponseLen = 0;
		CallServiceLoopByName(pXLoopServiceInfo->m_strName, NULL, NULL, 0, pResponseBuffer, szResponseLen);
		RELEASE(pResponseBuffer);
		uv_sleep(pXLoopServiceInfo->m_iInterval);
	}
}
static void getter_thread_body(void* arg) {
  char buffer[512];

  for (;;) {
    ASSERT(0 == uv_get_process_title(buffer, sizeof(buffer)));
    ASSERT(
      0 == strcmp(buffer, titles[0]) ||
      0 == strcmp(buffer, titles[1]) ||
      0 == strcmp(buffer, titles[2]) ||
      0 == strcmp(buffer, titles[3]));

    uv_sleep(0);
  }
}
예제 #6
0
파일: run-tests.c 프로젝트: 0x00A/uvxx
static int maybe_run_test(int argc, char **argv) {
  if (strcmp(argv[1], "--list") == 0) {
    print_tests(stdout);
    return 0;
  }

  if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
    return ipc_helper(0);
  }

  if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
    return ipc_helper(1);
  }

  if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
    return stdio_over_pipes_helper();
  }

  if (strcmp(argv[1], "spawn_helper1") == 0) {
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper2") == 0) {
    printf("hello world\n");
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper3") == 0) {
    char buffer[256];
    fgets(buffer, sizeof(buffer) - 1, stdin);
    buffer[sizeof(buffer) - 1] = '\0';
    fputs(buffer, stdout);
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper4") == 0) {
    /* Never surrender, never return! */
    while (1) uv_sleep(10000);
  }

  return run_test(argv[1], TEST_TIMEOUT, 0);
}
예제 #7
0
파일: test-async.c 프로젝트: benw/node
/* Thread 1 makes sure that async1_cb_called reaches 3 before exiting. */
void thread1_entry(void *arg) {
  uv_sleep(50);

  while (1) {
    switch (async1_cb_called) {
      case 0:
        uv_async_send(&async1_handle);
        break;

      case 1:
        uv_async_send(&async1_handle);
        break;

      case 2:
        uv_async_send(&async1_handle);
        break;

      default:
        return;
    }
  }
}
예제 #8
0
파일: test-async.c 프로젝트: benw/node
/* Thread 2 calls uv_async_send on async_handle_2 8 times. */
void thread2_entry(void *arg) {
  int i;

  while (1) {
    switch (async1_cb_called) {
      case 0:
        uv_async_send(&async2_handle);
        break;

      case 1:
        uv_async_send(&async2_handle);
        break;

      case 2:
        uv_async_send(&async2_handle);
        break;
    }
    uv_sleep(5);
  }

  if (async1_cb_called == 20) {
    uv_close(handle);
  }
}
예제 #9
0
파일: runner.c 프로젝트: Isszul/node
int run_test(const char* test,
             int timeout,
             int benchmark_output,
             int test_count) {
  char errmsg[1024] = "no error";
  process_info_t processes[1024];
  process_info_t *main_proc;
  task_entry_t* task;
  int process_count;
  int result;
  int status;
  int i;

  status = 255;
  main_proc = NULL;
  process_count = 0;

#ifndef _WIN32
  /* Clean up stale socket from previous run. */
  remove(TEST_PIPENAME);
#endif

  /* If it's a helper the user asks for, start it directly. */
  for (task = TASKS; task->main; task++) {
    if (task->is_helper && strcmp(test, task->process_name) == 0) {
      return task->main();
    }
  }

  /* Start the helpers first. */
  for (task = TASKS; task->main; task++) {
    if (strcmp(test, task->task_name) != 0) {
      continue;
    }

    /* Skip the test itself. */
    if (!task->is_helper) {
      continue;
    }

    if (process_start(task->task_name,
                      task->process_name,
                      &processes[process_count],
                      1 /* is_helper */) == -1) {
      snprintf(errmsg,
               sizeof errmsg,
               "Process `%s` failed to start.",
               task->process_name);
      goto out;
    }

    process_count++;
  }

  /* Give the helpers time to settle. Race-y, fix this. */
  uv_sleep(250);

  /* Now start the test itself. */
  for (task = TASKS; task->main; task++) {
    if (strcmp(test, task->task_name) != 0) {
      continue;
    }

    if (task->is_helper) {
      continue;
    }

    if (process_start(task->task_name,
                      task->process_name,
                      &processes[process_count],
                      0 /* !is_helper */) == -1) {
      snprintf(errmsg,
               sizeof errmsg,
               "Process `%s` failed to start.",
               task->process_name);
      goto out;
    }

    main_proc = &processes[process_count];
    process_count++;
    break;
  }

  if (main_proc == NULL) {
    snprintf(errmsg,
             sizeof errmsg,
             "No test with that name: %s",
             test);
    goto out;
  }

  result = process_wait(main_proc, 1, timeout);
  if (result == -1) {
    FATAL("process_wait failed");
  } else if (result == -2) {
    /* Don't have to clean up the process, process_wait() has killed it. */
    snprintf(errmsg,
             sizeof errmsg,
             "timeout");
    goto out;
  }

  status = process_reap(main_proc);
  if (status != 0) {
    snprintf(errmsg,
             sizeof errmsg,
             "exit code %d",
             status);
    goto out;
  }

  if (benchmark_output) {
    /* Give the helpers time to clean up their act. */
    uv_sleep(1000);
  }

out:
  /* Reap running processes except the main process, it's already dead. */
  for (i = 0; i < process_count - 1; i++) {
    process_terminate(&processes[i]);
  }

  if (process_count > 0 &&
      process_wait(processes, process_count - 1, -1) < 0) {
    FATAL("process_wait failed");
  }

  /* Show error and output from processes if the test failed. */
  if (status != 0 || task->show_output) {
    if (tap_output) {
      LOGF("not ok %d - %s\n#", test_count, test);
    } else if (status != 0) {
      LOGF("\n`%s` failed: %s\n", test, errmsg);
    } else {
      LOGF("\n");
    }

    for (i = 0; i < process_count; i++) {
      switch (process_output_size(&processes[i])) {
       case -1:
        LOGF("Output from process `%s`: (unavailable)\n",
             process_get_name(&processes[i]));
        break;

       case 0:
        LOGF("Output from process `%s`: (no output)\n",
             process_get_name(&processes[i]));
        break;

       default:
        LOGF("Output from process `%s`:\n", process_get_name(&processes[i]));
        process_copy_output(&processes[i], fileno(stderr));
        break;
      }
    }

    if (!tap_output) {
      LOG("=============================================================\n");
    }

  /* In benchmark mode show concise output from the main process. */
  } else if (benchmark_output) {
    switch (process_output_size(main_proc)) {
     case -1:
      LOGF("%s: (unavailable)\n", test);
      break;

     case 0:
      LOGF("%s: (no output)\n", test);
      break;

     default:
      for (i = 0; i < process_count; i++) {
        process_copy_output(&processes[i], fileno(stderr));
      }
      break;
    }
  } else if (tap_output) {
    LOGF("ok %d - %s\n", test_count, test);
  }

  /* Clean up all process handles. */
  for (i = 0; i < process_count; i++) {
    process_cleanup(&processes[i]);
  }

  return status;
}
예제 #10
0
파일: run-tests.c 프로젝트: basti1302/node
static int maybe_run_test(int argc, char **argv) {
  if (strcmp(argv[1], "--list") == 0) {
    print_tests(stdout);
    return 0;
  }

  if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
    return ipc_helper(0);
  }

  if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
    return ipc_helper(1);
  }

  if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
    return ipc_helper_heavy_traffic_deadlock_bug();
  }

  if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
    return ipc_send_recv_helper();
  }

  if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
    return ipc_helper_tcp_connection();
  }

  if (strcmp(argv[1], "ipc_helper_closed_handle") == 0) {
    return ipc_helper_closed_handle();
  }

  if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
    return ipc_helper_bind_twice();
  }

  if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
    return ipc_helper_send_zero();
  }

  if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
    return stdio_over_pipes_helper();
  }

  if (strcmp(argv[1], "spawn_helper1") == 0) {
    notify_parent_process();
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper2") == 0) {
    notify_parent_process();
    printf("hello world\n");
    return 1;
  }

  if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) {
    notify_parent_process();
    return spawn_tcp_server_helper();
  }

  if (strcmp(argv[1], "spawn_helper3") == 0) {
    char buffer[256];
    notify_parent_process();
    ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin));
    buffer[sizeof(buffer) - 1] = '\0';
    fputs(buffer, stdout);
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper4") == 0) {
    notify_parent_process();
    /* Never surrender, never return! */
    while (1) uv_sleep(10000);
  }

  if (strcmp(argv[1], "spawn_helper5") == 0) {
    const char out[] = "fourth stdio!\n";
    notify_parent_process();
    {
#ifdef _WIN32
      DWORD bytes;
      WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL);
#else
      ssize_t r;

      do
        r = write(3, out, sizeof(out) - 1);
      while (r == -1 && errno == EINTR);

      fsync(3);
#endif
    }
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper6") == 0) {
    int r;

    notify_parent_process();

    r = fprintf(stdout, "hello world\n");
    ASSERT(r > 0);

    r = fprintf(stderr, "hello errworld\n");
    ASSERT(r > 0);

    return 1;
  }

  if (strcmp(argv[1], "spawn_helper7") == 0) {
    int r;
    char *test;

    notify_parent_process();

    /* Test if the test value from the parent is still set */
    test = getenv("ENV_TEST");
    ASSERT(test != NULL);

    r = fprintf(stdout, "%s", test);
    ASSERT(r > 0);

    return 1;
  }

#ifndef _WIN32
  if (strcmp(argv[1], "spawn_helper8") == 0) {
    int fd;

    notify_parent_process();
    ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd)));
    ASSERT(fd > 2);
    ASSERT(-1 == write(fd, "x", 1));

    return 1;
  }
#endif  /* !_WIN32 */

  if (strcmp(argv[1], "spawn_helper9") == 0) {
    notify_parent_process();
    spawn_stdin_stdout();
    return 1;
  }

#ifndef _WIN32
  if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) {
    uv_uid_t uid = atoi(argv[2]);
    uv_gid_t gid = atoi(argv[3]);

    ASSERT(uid == getuid());
    ASSERT(gid == getgid());
    notify_parent_process();

    return 1;
  }
#endif  /* !_WIN32 */

  return run_test(argv[1], 0, 1);
}
예제 #11
0
파일: run-tests.c 프로젝트: JuliaLang/libuv
static int maybe_run_test(int argc, char **argv) {
  if (strcmp(argv[1], "--list") == 0) {
    print_tests(stdout);
    return 0;
  }

  if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
    return ipc_helper(0);
  }

  if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
    return ipc_helper(1);
  }

  if (strcmp(argv[1], "ipc_helper_heavy_traffic_deadlock_bug") == 0) {
    return ipc_helper_heavy_traffic_deadlock_bug();
  }

  if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
    return ipc_send_recv_helper();
  }

  if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
    return ipc_helper_tcp_connection();
  }

  if (strcmp(argv[1], "ipc_helper_closed_handle") == 0) {
    return ipc_helper_closed_handle();
  }

  if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) {
    return ipc_helper_bind_twice();
  }

  if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
    return stdio_over_pipes_helper();
  }

  if (strcmp(argv[1], "spawn_helper1") == 0) {
    notify_parent_process();
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper2") == 0) {
    notify_parent_process();
    printf("hello world\n");
    return 1;
  }

  if (strcmp(argv[1], "spawn_tcp_server_helper") == 0) {
    notify_parent_process();
    return spawn_tcp_server_helper();
  }

  if (strcmp(argv[1], "spawn_helper3") == 0) {
    char buffer[256];
    notify_parent_process();
    ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin));
    buffer[sizeof(buffer) - 1] = '\0';
    fputs(buffer, stdout);
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper4") == 0) {
    notify_parent_process();
    /* Never surrender, never return! */
    while (1) uv_sleep(10000);
  }

  if (strcmp(argv[1], "spawn_helper5") == 0) {
    const char out[] = "fourth stdio!\n";
    notify_parent_process();
#ifdef _WIN32
    DWORD bytes;
    WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL);
#else
    {
      ssize_t r;

      do
        r = write(3, out, sizeof(out) - 1);
      while (r == -1 && errno == EINTR);

      fsync(3);
    }
#endif
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper6") == 0) {
    int r;

    notify_parent_process();

    r = fprintf(stdout, "hello world\n");
    ASSERT(r > 0);

    r = fprintf(stderr, "hello errworld\n");
    ASSERT(r > 0);

    return 1;
  }

  if (strcmp(argv[1], "spawn_helper7") == 0) {
    int r;
    char *test;

    notify_parent_process();

    /* Test if the test value from the parent is still set */
    test = getenv("ENV_TEST");
    ASSERT(test != NULL);

    r = fprintf(stdout, "%s", test);
    ASSERT(r > 0);

    return 1;
  }

#ifndef _WIN32
  if (strcmp(argv[1], "spawn_helper8") == 0) {
    int fd;

    notify_parent_process();
    ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd)));
    ASSERT(fd > 2);
    ASSERT(-1 == write(fd, "x", 1));

    return 1;
  }
#endif  /* !_WIN32 */

  if (strcmp(argv[1], "spawn_helper9") == 0) {
    notify_parent_process();
    return spawn_stdin_stdout();
  }

#ifndef _WIN32
  if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) {
    uv_uid_t uid = atoi(argv[2]);
    uv_gid_t gid = atoi(argv[3]);

    ASSERT(uid == getuid());
    ASSERT(gid == getgid());
    notify_parent_process();

    return 1;
  }
#endif  /* !_WIN32 */

#if !defined(NO_CPU_AFFINITY)
  if (strcmp(argv[1], "spawn_helper_affinity") == 0) {
    int i;
    int r;
    int cpu;
    int cpumask_size;
#ifdef _WIN32
    DWORD_PTR procmask;
    DWORD_PTR sysmask;
#elif defined(__linux__)
    cpu_set_t cpuset;
#else
    cpuset_t cpuset;
#endif

    cpumask_size = uv_cpumask_size();
    ASSERT(cpumask_size > 0);

    cpu = atoi(argv[2]);
    ASSERT(cpu >= 0);
    ASSERT(cpu < cpumask_size);

    /* verify the mask has the cpu we expect */
#ifdef _WIN32
    r = GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask);
    ASSERT(r != 0);
    for (i = 0; i < cpumask_size; ++i) {
      ASSERT(((procmask & (((DWORD_PTR)1) << i)) != 0) == (i == cpu));
    }
#else
    CPU_ZERO(&cpuset);
    r = pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
    ASSERT(r == 0);
    for (i = 0; i < cpumask_size; ++i) {
      ASSERT(CPU_ISSET(i, &cpuset) == (i == cpu));
    }
#endif

    return 1;
  }
#endif

  return run_test(argv[1], 0, 1);
}
예제 #12
0
파일: runner.c 프로젝트: BrettQ/node
/*
 * Runs all processes associated with a particular test or benchmark.
 * It returns 1 if the test succeeded, 0 if it failed.
 * If the test fails it prints diagnostic information.
 * If benchmark_output is nonzero, the output from the main process is
 * always shown.
 */
int run_task(task_entry_t *test, int timeout, int benchmark_output) {
  int i, result, success;
  char errmsg[256];
  task_entry_t *helper;
  int process_count;
  process_info_t processes[MAX_PROCESSES];
  process_info_t *main_process;

  success = 0;

  process_count = 0;

  /* Start all helpers for this test first. */
  for (helper = (task_entry_t*)&TASKS; helper->main; helper++) {
    if (helper->is_helper &&
        strcmp(test->task_name, helper->task_name) == 0) {
      if (process_start(helper->process_name, &processes[process_count]) == -1) {
        snprintf((char*)&errmsg,
                 sizeof(errmsg),
                 "process `%s` failed to start.",
                 helper->process_name);
        goto finalize;
      }
      process_count++;
    }
  }

  /* Wait a little bit to allow servers to start. Racy. */
  uv_sleep(50);

  /* Start the main test process. */
  if (process_start(test->process_name, &processes[process_count]) == -1) {
    snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.",
        test->process_name);
    goto finalize;
  }
  main_process = &processes[process_count];
  process_count++;

  /* Wait for the main process to terminate. */
  result = process_wait(main_process, 1, timeout);
  if (result == -1) {
    FATAL("process_wait failed");
  } else if (result == -2) {
    snprintf((char*)&errmsg, sizeof(errmsg), "timeout.");
    goto finalize;
  }

  /* Reap the main process. */
  result = process_reap(main_process);
  if (result != 0) {
    snprintf((char*)&errmsg, sizeof(errmsg), "exit code %d.", result);
    goto finalize;
  }

  /* Yes! did it. */
  success = 1;

finalize:
  /* Kill all (helper) processes that are still running. */
  for (i = 0; i < process_count; i++) {
    /* If terminate fails the process is probably already closed. */
    process_terminate(&processes[i]);
  }

  /* Wait until all processes have really terminated. */
  if (process_wait((process_info_t*)&processes, process_count, -1) < 0) {
    FATAL("process_wait failed");
  }

  /* Show error and output from processes if the test failed. */
  if (!success) {
    LOGF("\n`%s` failed: %s\n", test->task_name, errmsg);

    for (i = 0; i < process_count; i++) {
      switch (process_output_size(&processes[i])) {
       case -1:
        LOGF("Output from process `%s`: (unavailable)\n",
             process_get_name(&processes[i]));
        break;

       case 0:
        LOGF("Output from process `%s`: (no output)\n",
             process_get_name(&processes[i]));
        break;

       default:
        LOGF("Output from process `%s`:\n", process_get_name(&processes[i]));
        process_copy_output(&processes[i], fileno(stderr));
        break;
      }
    }
    LOG("=============================================================\n");

  /* In benchmark mode show concise output from the main process. */
  } else if (benchmark_output) {
    switch (process_output_size(main_process)) {
     case -1:
      LOGF("%s: (unavailabe)\n", test->task_name);
      break;

     case 0:
      LOGF("%s: (no output)\n", test->task_name);
      break;

     default:
      //LOGF("%s: ", test->task_name);
      process_copy_output(main_process, fileno(stderr));
      break;
    }
  }

  /* Clean up all process handles. */
  for (i = 0; i < process_count; i++) {
    process_cleanup(&processes[i]);
  }

  return success;
}
예제 #13
0
파일: run-tests.c 프로젝트: 2hanson/node
static int maybe_run_test(int argc, char **argv) {
  if (strcmp(argv[1], "--list") == 0) {
    print_tests(stdout);
    return 0;
  }

  if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) {
    return ipc_helper(0);
  }

  if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) {
    return ipc_helper(1);
  }

  if (strcmp(argv[1], "ipc_send_recv_helper") == 0) {
    return ipc_send_recv_helper();
  }

  if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) {
    return ipc_helper_tcp_connection();
  }

  if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
    return stdio_over_pipes_helper();
  }

  if (strcmp(argv[1], "spawn_helper1") == 0) {
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper2") == 0) {
    printf("hello world\n");
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper3") == 0) {
    char buffer[256];
    fgets(buffer, sizeof(buffer) - 1, stdin);
    buffer[sizeof(buffer) - 1] = '\0';
    fputs(buffer, stdout);
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper4") == 0) {
    /* Never surrender, never return! */
    while (1) uv_sleep(10000);
  }

  if (strcmp(argv[1], "spawn_helper5") == 0) {
    const char* out = "fourth stdio!\n\0";
#ifdef _WIN32
    DWORD bytes;
    WriteFile((HANDLE) _get_osfhandle(3), out, strlen(out), &bytes, NULL);
#else
    write(3, out, strlen(out));
    fsync(3);
#endif
    return 1;
  }

  if (strcmp(argv[1], "spawn_helper6") == 0) {
    int r;

    r = fprintf(stdout, "hello world\n");
    ASSERT(r > 0);

    r = fprintf(stderr, "hello errworld\n");
    ASSERT(r > 0);

    return 1;
  }

  return run_test(argv[1], TEST_TIMEOUT, 0);
}