Alien-uv

 view release on metacpan or  search on metacpan

libuv/src/win/pipe.c  view on Meta::CPAN

        goto error;
      }

      REGISTER_HANDLE_REQ(loop, handle, req);
      handle->reqs_pending++;

      return;
    }

    err = GetLastError();
    goto error;
  }

  assert(pipeHandle != INVALID_HANDLE_VALUE);

  if (uv_set_pipe_handle(loop,
                         (uv_pipe_t*) req->handle,
                         pipeHandle,
                         -1,
                         duplex_flags)) {
    err = GetLastError();
    goto error;
  }

  SET_REQ_SUCCESS(req);
  uv_insert_pending_req(loop, (uv_req_t*) req);
  handle->reqs_pending++;
  REGISTER_HANDLE_REQ(loop, handle, req);
  return;

error:
  if (handle->name) {
    uv__free(handle->name);
    handle->name = NULL;
  }

  if (pipeHandle != INVALID_HANDLE_VALUE) {
    CloseHandle(pipeHandle);
  }

  /* Make this req pending reporting an error. */
  SET_REQ_ERROR(req, err);
  uv_insert_pending_req(loop, (uv_req_t*) req);
  handle->reqs_pending++;
  REGISTER_HANDLE_REQ(loop, handle, req);
  return;
}


void uv__pipe_interrupt_read(uv_pipe_t* handle) {
  BOOL r;

  if (!(handle->flags & UV_HANDLE_READ_PENDING))
    return; /* No pending reads. */
  if (handle->flags & UV_HANDLE_CANCELLATION_PENDING)
    return; /* Already cancelled. */
  if (handle->handle == INVALID_HANDLE_VALUE)
    return; /* Pipe handle closed. */

  if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {
    /* Cancel asynchronous read. */
    r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
    assert(r || GetLastError() == ERROR_NOT_FOUND);

  } else {
    /* Cancel synchronous read (which is happening in the thread pool). */
    HANDLE thread;
    volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;

    EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);

    thread = *thread_ptr;
    if (thread == NULL) {
      /* The thread pool thread has not yet reached the point of blocking, we
       * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */
      *thread_ptr = INVALID_HANDLE_VALUE;

    } else {
      /* Spin until the thread has acknowledged (by setting the thread to
       * INVALID_HANDLE_VALUE) that it is past the point of blocking. */
      while (thread != INVALID_HANDLE_VALUE) {
        r = CancelSynchronousIo(thread);
        assert(r || GetLastError() == ERROR_NOT_FOUND);
        SwitchToThread(); /* Yield thread. */
        thread = *thread_ptr;
      }
    }

    LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);
  }

  /* Set flag to indicate that read has been cancelled. */
  handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
}


void uv__pipe_read_stop(uv_pipe_t* handle) {
  handle->flags &= ~UV_HANDLE_READING;
  DECREASE_ACTIVE_COUNT(handle->loop, handle);

  uv__pipe_interrupt_read(handle);
}


/* Cleans up uv_pipe_t (server or connection) and all resources associated with
 * it. */
void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
  int i;
  HANDLE pipeHandle;

  uv__pipe_interrupt_read(handle);

  if (handle->name) {
    uv__free(handle->name);
    handle->name = NULL;
  }

  if (handle->flags & UV_HANDLE_PIPESERVER) {
    for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
      pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle;
      if (pipeHandle != INVALID_HANDLE_VALUE) {
        CloseHandle(pipeHandle);
        handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
      }
    }
    handle->handle = INVALID_HANDLE_VALUE;

libuv/src/win/pipe.c  view on Meta::CPAN

                                      &io_status,
                                      &access,
                                      sizeof(access),
                                      FileAccessInformation);
  if (nt_status != STATUS_SUCCESS)
    return UV_EINVAL;

  if (pipe->ipc) {
    if (!(access.AccessFlags & FILE_WRITE_DATA) ||
        !(access.AccessFlags & FILE_READ_DATA)) {
      return UV_EINVAL;
    }
  }

  if (access.AccessFlags & FILE_WRITE_DATA)
    duplex_flags |= UV_HANDLE_WRITABLE;
  if (access.AccessFlags & FILE_READ_DATA)
    duplex_flags |= UV_HANDLE_READABLE;

  if (os_handle == INVALID_HANDLE_VALUE ||
      uv_set_pipe_handle(pipe->loop,
                         pipe,
                         os_handle,
                         file,
                         duplex_flags) == -1) {
    return UV_EINVAL;
  }

  uv_pipe_connection_init(pipe);

  if (pipe->ipc) {
    assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
    pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
    assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1);
  }
  return 0;
}


static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) {
  NTSTATUS nt_status;
  IO_STATUS_BLOCK io_status;
  FILE_NAME_INFORMATION tmp_name_info;
  FILE_NAME_INFORMATION* name_info;
  WCHAR* name_buf;
  unsigned int addrlen;
  unsigned int name_size;
  unsigned int name_len;
  int err;

  uv__once_init();
  name_info = NULL;

  if (handle->handle == INVALID_HANDLE_VALUE) {
    *size = 0;
    return UV_EINVAL;
  }

  /* NtQueryInformationFile will block if another thread is performing a
   * blocking operation on the queried handle. If the pipe handle is
   * synchronous, there may be a worker thread currently calling ReadFile() on
   * the pipe handle, which could cause a deadlock. To avoid this, interrupt
   * the read. */
  if (handle->flags & UV_HANDLE_CONNECTION &&
      handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
    uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */
  }

  nt_status = pNtQueryInformationFile(handle->handle,
                                      &io_status,
                                      &tmp_name_info,
                                      sizeof tmp_name_info,
                                      FileNameInformation);
  if (nt_status == STATUS_BUFFER_OVERFLOW) {
    name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
    name_info = uv__malloc(name_size);
    if (!name_info) {
      *size = 0;
      err = UV_ENOMEM;
      goto cleanup;
    }

    nt_status = pNtQueryInformationFile(handle->handle,
                                        &io_status,
                                        name_info,
                                        name_size,
                                        FileNameInformation);
  }

  if (nt_status != STATUS_SUCCESS) {
    *size = 0;
    err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status));
    goto error;
  }

  if (!name_info) {
    /* the struct on stack was used */
    name_buf = tmp_name_info.FileName;
    name_len = tmp_name_info.FileNameLength;
  } else {
    name_buf = name_info->FileName;
    name_len = name_info->FileNameLength;
  }

  if (name_len == 0) {
    *size = 0;
    err = 0;
    goto error;
  }

  name_len /= sizeof(WCHAR);

  /* check how much space we need */
  addrlen = WideCharToMultiByte(CP_UTF8,
                                0,
                                name_buf,
                                name_len,
                                NULL,
                                0,
                                NULL,
                                NULL);



( run in 0.502 second using v1.01-cache-2.11-cpan-411bb0df24b )