Esempio n. 1
0
static void accept_loop(FileDescriptor&& listenerDescriptor) {
  auto listener = w_stm_fdopen(std::move(listenerDescriptor));
  while (!stopping) {
    FileDescriptor client_fd;
    struct watchman_event_poll pfd[2];
    int bufsize;

#ifdef HAVE_LIBGIMLI_H
    if (hb) {
      gimli_heartbeat_set(hb, GIMLI_HB_RUNNING);
    }
#endif

    pfd[0].evt = listener->getEvents();
    pfd[1].evt = listener_thread_event.get();

    if (w_poll_events(pfd, 2, 60000) == 0) {
      if (stopping) {
        break;
      }
      // Timed out, or error.
      // Arrange to sanity check that we're working
      w_check_my_sock();
      continue;
    }

    if (stopping) {
      break;
    }

#ifdef HAVE_ACCEPT4
    client_fd = FileDescriptor(
        accept4(listener->getFileDescriptor().fd(), nullptr, 0, SOCK_CLOEXEC));
#else
    client_fd =
        FileDescriptor(accept(listener->getFileDescriptor().fd(), nullptr, 0));
#endif
    if (!client_fd) {
      continue;
    }
    client_fd.setCloExec();
    bufsize = WATCHMAN_IO_BUF_SIZE;
    setsockopt(
        client_fd.fd(),
        SOL_SOCKET,
        SO_SNDBUF,
        (void*)&bufsize,
        sizeof(bufsize));

    make_new_client(w_stm_fdopen(std::move(client_fd)));
  }
}
Esempio n. 2
0
// If we are running under inetd-style supervision, call this function
// to move the inetd provided socket descriptor(s) to a new descriptor
// number and remember that we can just use these when we're starting
// up the listener.
void w_listener_prep_inetd() {
  if (listener_fd) {
    throw std::runtime_error(
        "w_listener_prep_inetd: listener_fd is already assigned");
  }

  listener_fd = FileDescriptor(dup(STDIN_FILENO), "dup(stdin) for listener");
}
Esempio n. 3
0
static FileDescriptor create_pipe_server(const char* path) {
  return FileDescriptor(intptr_t(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,
      nullptr)));
}
Esempio n. 4
0
static FileDescriptor get_listener_socket(const char *path)
{
  struct sockaddr_un un;
  mode_t perms = cfg_get_perms(
      "sock_access", true /* write bits */, false /* execute bits */);
  FileDescriptor listener_fd;

#ifdef __APPLE__
  listener_fd = w_get_listener_socket_from_launchd();
  if (listener_fd) {
    w_log(W_LOG_ERR, "Using socket from launchd as listening socket\n");
    return listener_fd;
  }
#endif

  if (strlen(path) >= sizeof(un.sun_path) - 1) {
    w_log(W_LOG_ERR, "%s: path is too long\n",
        path);
    return FileDescriptor();
  }

  listener_fd = FileDescriptor(socket(PF_LOCAL, SOCK_STREAM, 0), "socket");

  un.sun_family = PF_LOCAL;
  memcpy(un.sun_path, path, strlen(path) + 1);
  unlink(path);

  if (bind(listener_fd.fd(), (struct sockaddr*)&un, sizeof(un)) != 0) {
    w_log(W_LOG_ERR, "bind(%s): %s\n",
      path, strerror(errno));
    return FileDescriptor();
  }

  // The permissions in the containing directory should be correct, so this
  // should be correct as well. But set the permissions in any case.
  if (chmod(path, perms) == -1) {
    w_log(W_LOG_ERR, "chmod(%s, %#o): %s", path, perms, strerror(errno));
    return FileDescriptor();
  }

  // Double-check that the socket has the right permissions. This can happen
  // when the containing directory was created in a previous run, with a group
  // the user is no longer in.
  struct stat st;
  if (lstat(path, &st) == -1) {
    watchman::log(watchman::ERR, "lstat(", path, "): ", strerror(errno), "\n");
    return FileDescriptor();
  }

  // This is for testing only
  // (test_sock_perms.py:test_user_previously_in_sock_group). Do not document.
  const char *sock_group_name = cfg_get_string("__sock_file_group", nullptr);
  if (!sock_group_name) {
    sock_group_name = cfg_get_string("sock_group", nullptr);
  }

  if (sock_group_name) {
    const struct group *sock_group = w_get_group(sock_group_name);
    if (!sock_group) {
      return FileDescriptor();
    }
    if (st.st_gid != sock_group->gr_gid) {
      watchman::log(
        watchman::ERR,
        "for socket '", path, "', gid ", st.st_gid,
        " doesn't match expected gid ", sock_group->gr_gid, " (group name ",
        sock_group_name, "). Ensure that you are still a member of group ",
        sock_group_name, ".\n");
      return FileDescriptor();
    }
  }

  if (listen(listener_fd.fd(), 200) != 0) {
    w_log(W_LOG_ERR, "listen(%s): %s\n",
        path, strerror(errno));
    return FileDescriptor();
  }

  return listener_fd;
}
Esempio n. 5
0
static void named_pipe_accept_loop_internal(const char* path) {
  HANDLE handles[2];
  auto olap = OVERLAPPED();
  HANDLE connected_event = CreateEvent(NULL, FALSE, TRUE, NULL);

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

  handles[0] = connected_event;
  handles[1] = listener_thread_event;
  olap.hEvent = connected_event;

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

    client_fd = FileDescriptor(intptr_t(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,
        nullptr)));

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

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

      if (res == ERROR_PIPE_CONNECTED) {
        make_new_client(w_stm_fdopen(std::move(client_fd)));
        continue;
      }

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

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

      if (res != WAIT_OBJECT_0) {
        w_log(
            W_LOG_ERR,
            "WaitForMultipleObjectsEx: ConnectNamedPipe: "
            "unexpected status %u\n",
            res);
        CancelIoEx((HANDLE)client_fd.handle(), &olap);
        continue;
      }
    }
    make_new_client(w_stm_fdopen(std::move(client_fd)));
  }
}
Esempio n. 6
0
KQueueWatcher::KQueueWatcher(w_root_t* root)
    : Watcher("kqueue", 0),
      maps_(maps(root->config.getInt(CFG_HINT_NUM_DIRS, HINT_NUM_DIRS))) {
  kq_fd = FileDescriptor(kqueue(), "kqueue");
  kq_fd.setCloExec();
}