Example #1
0
w_stm_t w_stm_connect_named_pipe(const char *path, int timeoutms) {
  w_stm_t stm = NULL;
  HANDLE handle;
  DWORD err;
  DWORD64 deadline = GetTickCount64() + timeoutms;

  if (strlen(path) > 255) {
    w_log(W_LOG_ERR, "w_stm_connect_named_pipe(%s) path is too long\n", path);
    errno = E2BIG;
    return NULL;
  }

retry_connect:
  handle = CreateFile(path,
      GENERIC_READ|GENERIC_WRITE,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_FLAG_OVERLAPPED,
      NULL);

  if (handle != INVALID_HANDLE_VALUE) {
    stm = w_stm_handleopen(handle);
    if (!stm) {
      CloseHandle(handle);
    }
    return stm;
  }

  err = GetLastError();
  if (timeoutms > 0) {
    timeoutms -= (DWORD)(GetTickCount64() - deadline);
  }
  if (timeoutms <= 0 || (err != ERROR_PIPE_BUSY &&
        err != ERROR_FILE_NOT_FOUND)) {
    // either we're out of time, or retrying won't help with this error
    errno = map_win32_err(err);
    return NULL;
  }

  // We can retry
  if (!WaitNamedPipe(path, timeoutms)) {
    err = GetLastError();
    if (err == ERROR_SEM_TIMEOUT) {
      errno = map_win32_err(err);
      return NULL;
    }
    if (err == ERROR_FILE_NOT_FOUND) {
      // Grace to allow it to be created
      SleepEx(10, true);
    }
  }

  goto retry_connect;
}
Example #2
0
w_stm_t w_stm_open(const char *path, int flags, ...) {
  w_stm_t stm;
  HANDLE h = w_handle_open(path, flags);

  if (h == INVALID_HANDLE_VALUE) {
    return NULL;
  }

  stm = w_stm_handleopen(h);
  if (!stm) {
    CloseHandle(h);
  }
  return stm;
}
Example #3
0
static void named_pipe_accept_loop(const char *path) {
  HANDLE handles[2];
  OVERLAPPED olap;
  HANDLE connected_event = CreateEvent(NULL, FALSE, TRUE, NULL);

  if (!connected_event) {
    w_log(W_LOG_ERR, "named_pipe_accept_loop: CreateEvent failed: %s\n",
        win32_strerror(GetLastError()));
    return;
  }

  listener_thread_event = CreateEvent(NULL, FALSE, TRUE, NULL);

  handles[0] = connected_event;
  handles[1] = listener_thread_event;
  memset(&olap, 0, sizeof(olap));
  olap.hEvent = connected_event;

  w_log(W_LOG_ERR, "waiting for pipe clients on %s\n", path);
  while (!stopping) {
    w_stm_t stm;
    HANDLE client_fd;
    DWORD res;

    client_fd = CreateNamedPipe(
        path,
        PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
        PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|
        PIPE_REJECT_REMOTE_CLIENTS,
        PIPE_UNLIMITED_INSTANCES,
        WATCHMAN_IO_BUF_SIZE,
        512, 0, NULL);

    if (client_fd == INVALID_HANDLE_VALUE) {
      w_log(W_LOG_ERR, "CreateNamedPipe(%s) failed: %s\n",
          path, win32_strerror(GetLastError()));
      continue;
    }

    ResetEvent(connected_event);
    if (!ConnectNamedPipe(client_fd, &olap)) {
      res = GetLastError();

      if (res == ERROR_PIPE_CONNECTED) {
        goto good_client;
      }

      if (res != ERROR_IO_PENDING) {
        w_log(W_LOG_ERR, "ConnectNamedPipe: %s\n",
            win32_strerror(GetLastError()));
        CloseHandle(client_fd);
        continue;
      }

      res = WaitForMultipleObjectsEx(2, handles, false, INFINITE, true);
      if (res == WAIT_OBJECT_0 + 1) {
        // Signalled to stop
        CancelIoEx(client_fd, &olap);
        CloseHandle(client_fd);
        continue;
      }

      if (res == WAIT_OBJECT_0) {
        goto good_client;
      }

      w_log(W_LOG_ERR, "WaitForMultipleObjectsEx: ConnectNamedPipe: "
          "unexpected status %u\n", res);
      CancelIoEx(client_fd, &olap);
      CloseHandle(client_fd);
    } else {
good_client:
      stm = w_stm_handleopen(client_fd);
      if (!stm) {
        w_log(W_LOG_ERR, "Failed to allocate stm for pipe handle: %s\n",
            strerror(errno));
        CloseHandle(client_fd);
        continue;
      }

      make_new_client(stm);
    }
  }
}