Exemple #1
0
static int ghbn_init(rktio_t *rktio)
{
  rktio->ghbn_lock = CreateSemaphore(NULL, 1, 1, NULL);
  if (!rktio->ghbn_lock) {
    get_windows_error();
    return 0;
  }
  rktio->ghbn_start = CreateSemaphore(NULL, 0, 1, NULL);
  if (!rktio->ghbn_start) {
    get_windows_error();
    return 0;
  }
  rktio->ghbn_th = (HANDLE)_beginthreadex(NULL, 5000, 
                                          win_getaddrinfo_in_thread,
                                          rktio, 0, NULL);
  if (rktio->ghbn_th == INVALID_HANDLE_VALUE) {
    get_posix_error();
    return 0;
  }
  
  return 1;
}
Exemple #2
0
rktio_status_t *rktio_process_status(rktio_t *rktio, rktio_process_t *sp)
{
  int going = 0, status = 0;
  rktio_status_t *result;

#if defined(RKTIO_SYSTEM_UNIX)
# if defined(CENTRALIZED_SIGCHILD)
  if (sp->done) {
    status = sp->status;
  } else {
    if (!centralized_get_child_status(sp->pid, sp->in_group, 1, &status)) {
      going = 1;
    } else {
      sp->done = 1;
      sp->status = status;
      centralized_ended_child();
    }
  }
# else
  System_Child *sc = (System_Child *)sp->handle;
  check_child_done(rktio, sp->pid);

  if (sc->done) {
    status = sc->status;
  } else
   going = 1;
# endif
#else
# ifdef RKTIO_SYSTEM_WINDOWS
  DWORD w;
  if (sp->handle) {
    if (GetExitCodeProcess((HANDLE)sp->handle, &w)) {
      collect_process_time(rktio, w, sp);
      if (w == STILL_ACTIVE)
        going = 1;
      else
        status = w;
    } else {
      get_windows_error();
      return NULL;
    }
  } else
    status = -1;
# endif
#endif

  result = malloc(sizeof(rktio_status_t));
  result->running = going;
  result->result = (going ? 0 : status);
  return result;
}
Exemple #3
0
int rktio_poll_process_done(rktio_t *rktio, rktio_process_t *sp)
{
#if defined(RKTIO_SYSTEM_UNIX)
# if defined(CENTRALIZED_SIGCHILD)
  {
    int status;
    if (!sp->done) {
      if (centralized_get_child_status(sp->pid, sp->in_group, 1, &status)) {
        sp->done = 1;
        sp->status = status;
        centralized_ended_child();
        return 1;
      }
      return 0;
    }
    else
      return RKTIO_PROCESS_DONE;
  }
# else
  {
    System_Child *sc;
    sc = (System_Child *)sp->handle;
    /* Check specific pid, in case the child has its own group
       (either given by us or given to itself): */
    check_child_done(rktio, sp->pid);
    return sc->done;
  }
# endif
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
  {
    HANDLE sci = (HANDLE)sp->handle;
    DWORD w;
    if (sci) {
      if (GetExitCodeProcess(sci, &w)) {
        collect_process_time(rktio, w, sp);
        return (w != STILL_ACTIVE);
      } else
        return RKTIO_PROCESS_DONE;
    } else
      return RKTIO_PROCESS_DONE;

    get_windows_error();

    return RKTIO_PROCESS_ERROR;
  }
#endif
}
Exemple #4
0
static rktio_ok_t do_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error)
{
  int ok;

#ifdef RKTIO_SYSTEM_UNIX
  int cr;

# ifdef RKTIO_USE_FCNTL_AND_FORK_FOR_FILE_LOCKS
  if (!(rfd->modes & RKTIO_OPEN_SOCKET))
    rktio_release_lockf(rktio, rfd->fd);
# endif

  cr = rktio_reliably_close_err(rfd->fd);

  if (cr && set_error) {
    get_posix_error();   
    ok = 0;
  } else
    ok = 1;
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
  if (rfd->modes & RKTIO_OPEN_SOCKET)
    return rktio_socket_close(rktio, rfd, set_error);

  deinit_fd(rktio, rfd, 1);

  ok = 1;
  if (!rfd->th && !rfd->oth) {
    if (!CloseHandle(rfd->fd)) {
      ok = 0;
      get_windows_error();
    }
  }
  
#endif

  if (ok)
    free(rfd);
  
  return ok;
}
Exemple #5
0
rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd)
{
#ifdef RKTIO_SYSTEM_UNIX
  intptr_t nfd;

  do {
    nfd = dup(rfd->fd);
  } while (nfd == -1 && errno == EINTR);

  if (nfd == -1) {
    get_posix_error();
    return NULL;
  } else {
    /* Set the `RKTIO_OPEN_INIT` flag, because dup()ing a file
       descriptor does not keep all of its properties on some
       platforms (e.g., the non-blocking property on sockets on
       Linux). */
    return rktio_system_fd(rktio, nfd, rfd->modes | RKTIO_OPEN_INIT);
  }
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
  if (rfd->modes & RKTIO_OPEN_SOCKET) {
    return rktio_socket_dup(rktio, rfd);
  } else {
    HANDLE  newhandle;
    BOOL rc;

    rc = DuplicateHandle(GetCurrentProcess(), rfd->fd,
                         GetCurrentProcess(), &newhandle,
                         0, FALSE, DUPLICATE_SAME_ACCESS);

    if (rc == FALSE) {
      get_windows_error();
      return NULL;
    } else {
      return rktio_system_fd(rktio, (intptr_t)newhandle, rfd->modes);
    }
  }
#endif
}
Exemple #6
0
static rktio_addrinfo_lookup_t *start_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup)
{
  lookup->mode = GHBN_WAIT;
  
  if (!rktio->ghbn_started) {
    rktio->ghbn_run = 1;
    if (!ghbn_init(rktio))
      return NULL;
    rktio->ghbn_started = 1;
  }

# ifdef RKTIO_SYSTEM_WINDOWS
  {
    lookup->done_sema = CreateSemaphore(NULL, 0, 1, NULL);
    if (!lookup->done_sema) {
      get_windows_error();
      free_lookup(lookup);
      return NULL;
    }
  }
# else
  if (pipe(lookup->done_fd)) {
    get_posix_error();
    free_lookup(lookup);
    return NULL;
  } else {
    fcntl(lookup->done_fd[0], F_SETFL, RKTIO_NONBLOCKING);
  }
# endif

  ghbn_lock(rktio);
  lookup->next = rktio->ghbn_requests;
  rktio->ghbn_requests = lookup;
  ghbn_signal(rktio);
  ghbn_unlock(rktio);

  return lookup;
}
Exemple #7
0
int rktio_winsock_init(rktio_t *rktio)
{
  if (!winsock_sema) {
    winsock_sema = CreateSemaphore(NULL, 1, 1, NULL);
  }

  WaitForSingleObject(winsock_sema, INFINITE);

  if (!winsock_started) {
    WSADATA data;
    if (!WSAStartup(MAKEWORD(1, 1), &data)) {
      winsock_started = 1;
    } else {
      get_windows_error();
      ReleaseSemaphore(winsock_sema, 1, NULL);
      return 0;
    }
  } else
    winsock_started++;
  
  ReleaseSemaphore(winsock_sema, 1, NULL);

  return 1;
}
Exemple #8
0
static int do_subprocess_kill(rktio_t *rktio, rktio_process_t *sp, int as_kill)
{
#if defined(RKTIO_SYSTEM_UNIX)
# if defined(CENTRALIZED_SIGCHILD)
  {
    int status;

    if (sp->done)
      return 1;

    centralized_wait_suspend();

    /* Don't allow group checking, because we don't want to wait
       on a group if we haven't already: */
    if (centralized_get_child_status(sp->pid, 0, 0, &status)) {
      sp->status = status;
      sp->done = 1;
      centralized_wait_resume();
      centralized_ended_child();
      return 1;
    }
  }
# else
  {
    System_Child *sc = (System_Child *)sp->handle;

    /* Don't pass sp->pid, because we don't want to wait
       on a group if we haven't already: */
    check_child_done(rktio, 0);
    if (sc->done)
      return 1;
  }
# define centralized_wait_resume() /* empty */
# endif

  while (1) {

    if (sp->is_group) {
      if (!killpg(sp->pid, as_kill ? SIGKILL : SIGINT)) {
        centralized_wait_resume();
        return 1;
      }
    } else {
      if (!kill(sp->pid, as_kill ? SIGKILL : SIGINT)) {
        centralized_wait_resume();
        return 1;
      }
    }
    
    if (errno != EINTR)
      break;
    /* Otherwise we were interrupted. Try `kill' again. */
  }

  get_posix_error();

  centralized_wait_resume();

  return 0;
#endif
#if defined(RKTIO_SYSTEM_WINDOWS)  
  if (as_kill || sp->is_group) {
    DWORD w;

    if (!sp->handle)
      return 1;

    if (!as_kill) {
      /* must be for a group; we don't care whether the
         original process is still running */
      if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, sp->pid))
        return 1;
    } else if (GetExitCodeProcess((HANDLE)sp->handle, &w)) {
      collect_process_time(rktio, w, sp);
      if (w != STILL_ACTIVE)
        return 1;
      if (TerminateProcess((HANDLE)sp->handle, 1))
        return 1;
    }
    get_windows_error();

    return 0;
  } else
    return 1;
#endif
}
Exemple #9
0
intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len,
                              char *is_converted)
{
#ifdef RKTIO_SYSTEM_UNIX
  intptr_t bc;

  if (rfd->modes & RKTIO_OPEN_SOCKET)
    return rktio_socket_read(rktio, rfd, buffer, len);

# ifdef SOME_FDS_ARE_NOT_SELECTABLE
  if (rfd->bufcount && len) {
    buffer[0] = rfd->buffer[0];
    rfd->bufcount = 0;
    return 1;
  }
# endif

  if (rktio_fd_is_regular_file(rktio, rfd)) {
    /* Reading regular file never blocks */
    do {
      bc = read(rfd->fd, buffer, len);
    } while ((bc == -1) && (errno == EINTR));

    if (bc == -1) {
      get_posix_error();
      return RKTIO_READ_ERROR;
    } else if (bc == 0)
      return RKTIO_READ_EOF;
    else
      return bc;
  } else {
    /* We use a non-blocking read here, even though we've waited
       for input above, because an external process might have
       gobbled the characters that we expected to get. */
    int old_flags;
    
    old_flags = fcntl(rfd->fd, F_GETFL, 0);
    if (!(old_flags & RKTIO_NONBLOCKING))
      fcntl(rfd->fd, F_SETFL, old_flags | RKTIO_NONBLOCKING);
    
    do {
      bc = read(rfd->fd, buffer, len);
    } while ((bc == -1) && errno == EINTR);

    if ((bc == -1) && (errno != EAGAIN))
      get_posix_error();
    
    if (!(old_flags & RKTIO_NONBLOCKING))
      fcntl(rfd->fd, F_SETFL, old_flags);
    
    if (bc == -1) {
      if (errno == EAGAIN)
        return 0; /* no bytes from a non-blocking read */
      else
        return RKTIO_READ_ERROR;
    } else if (bc == 0)
      return RKTIO_READ_EOF;
    else
      return bc;
  }
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
  if (rfd->modes & RKTIO_OPEN_SOCKET)
    return rktio_socket_read(rktio, rfd, buffer, len);

  init_read_fd(rktio, rfd);

  if (!rfd->th) {
    /* We can read directly. This must be a regular file, where
       reading never blocks. */
    DWORD rgot, offset = 0;

    if (rfd->has_pending_byte) {
      if (!len)
	return 0;
      buffer[0] = rfd->pending_byte;
      if (len == 1) {
	if (rfd->pending_byte == '\r') {
	  /* We have to read one more byte and then decode,
	     shifting the new byte into pending position
	     if it's not '\n' */
	} else {
	  if (is_converted) is_converted[0] = 0;
	  rfd->has_pending_byte = 0;
	  return 1;
	}
      } else {
	/* read after first byte installed into the buffer */
	offset = 1;
      }
    }
    
    if (!ReadFile((HANDLE)rfd->fd, buffer + offset, len - offset, &rgot, NULL)) {
      get_windows_error();
      return RKTIO_READ_ERROR;
    }
    rgot += offset;
    
    if (rfd->has_pending_byte) {
      /* We had a buffer of size 1 and a pending '\r'... */
      return adjust_input_text_for_pending_cr(rfd, buffer, is_converted, rgot);
    } else if (!rgot)
      return RKTIO_READ_EOF;
    else if (rfd->modes & RKTIO_OPEN_TEXT)
      return adjust_input_text(rfd, buffer, is_converted, rgot, offset);
    else
      return rgot;
  } else {
    if (!rktio_poll_read_ready(rktio, rfd))
      return 0;
    
    /* If we get this far, there should be data available.
       Extract data made available by the reader thread. */
    WaitForSingleObject(rfd->th->lock_sema, INFINITE);
    if (rfd->th->eof) {
      if (rfd->th->eof != INVALID_HANDLE_VALUE) {
        ReleaseSemaphore(rfd->th->eof, 1, NULL);
        rfd->th->eof = NULL;
      }
      ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
      return RKTIO_READ_EOF;
    } else if (rfd->th->err) {
      ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
      set_windows_error(rfd->th->err);
      return RKTIO_READ_ERROR;
    } else {
      intptr_t bc = rfd->th->avail;
      if (bc > len)
	bc = len;
      rfd->th->avail -= bc;
      memcpy(buffer, rfd->buffer + rfd->th->offset, bc);
      rfd->th->offset += bc;
      ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
      return bc;
    }
  }
#endif
}
Exemple #10
0
        mapped_file::mapped_file(const string & fname, unsigned int io_open_mode, unsigned int create_size)
            : file_handle(0), map_handle(0), map_pointer(0)
        {
#ifdef WIN32
            string full_path = io::file::get_full_path(fname);

            // open file handle
            unsigned int win_open_mode = GENERIC_READ;

            if (io_open_mode & io::FILE_OPEN_WRITE)
                win_open_mode |= GENERIC_WRITE;

            if (file::exists(full_path))
            {
                file_handle = CreateFileW(full_path.w_string(), win_open_mode, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

                if (file_handle != INVALID_HANDLE_VALUE)
                    create_size = GetFileSize(file_handle, 0);
            }
            else
            {
                if (create_size == 0)
                    throw internal_exception(__FILE__, __LINE__, L"Must specify size for creating memory-mapped files.");

                file_handle = CreateFileW(full_path.w_string(), win_open_mode, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
                
                if (file_handle != INVALID_HANDLE_VALUE)
                {
                    unsigned char buf = 0;
                    unsigned int written;
                    SetFilePointer(file_handle, create_size-1, 0, FILE_BEGIN);                    
                    WriteFile(file_handle, &buf, 1, (LPDWORD) &written, 0);
                    SetFilePointer(file_handle, 0, 0, FILE_BEGIN);
                }
            }
            
            if (file_handle == INVALID_HANDLE_VALUE)
                throw io_exception(L"Unable to open %ls: %ls", full_path.w_string(), get_windows_error().w_string());

            // create mapping
            string map_name = string::format(L"periapsis_mapped_file_%d", NUM_MAPPED_FILES++);

            if (io_open_mode & io::FILE_OPEN_WRITE)
                win_open_mode = PAGE_READWRITE;
            else
                win_open_mode = PAGE_READONLY;

            map_handle = CreateFileMappingW(file_handle, 0, win_open_mode, 0, create_size, map_name.w_string());

            if (!map_handle)
                throw io_exception(L"Unable to create memory map for %ls: %ls", full_path.w_string(), get_windows_error().w_string());

            // map file
            if (io_open_mode & io::FILE_OPEN_WRITE)
                win_open_mode = FILE_MAP_ALL_ACCESS;
            else
                win_open_mode = FILE_MAP_READ;

            map_pointer = MapViewOfFile(map_handle, win_open_mode, 0, 0, 0);

            if (!map_pointer)
                throw io_exception(L"Unable to create memory map for %ls: %ls", full_path.w_string(), get_windows_error().w_string());

            map_size = create_size;
#else
#error Implement memory-mapped files!
#endif
        } // mapped_file::mapped_file()