示例#1
0
static void setup_sock_name(void)
{
  const char *user = compute_user_name();

  watchman_tmp_dir = get_env_with_fallback("TMPDIR", "TMP", "/tmp");

#ifdef _WIN32
  if (!sock_name) {
    asprintf(&sock_name, "\\\\.\\pipe\\watchman-%s", user);
  }
#else
  compute_file_name(&sock_name, user, "sock", "sockname");
#endif
  compute_file_name(&watchman_state_file, user, "state", "statefile");
  compute_file_name(&log_name, user, "log", "logname");
#ifdef USE_GIMLI
  compute_file_name(&pid_file, user, "pid", "pidfile");
#endif

#ifndef _WIN32
  un.sun_family = PF_LOCAL;
  strcpy(un.sun_path, sock_name);

  if (strlen(sock_name) >= sizeof(un.sun_path) - 1) {
    w_log(W_LOG_ERR, "%s: path is too long\n",
        sock_name);
    abort();
  }
#endif
}
示例#2
0
static bool lock_pidfile(void) {
#if !defined(USE_GIMLI) && !defined(_WIN32)
  struct flock lock;
  pid_t mypid;
  int fd;

  // We defer computing this path until we're in the server context because
  // eager evaluation can trigger integration test failures unless all clients
  // are aware of both the pidfile and the sockpath being used in the tests.
  compute_file_name(&pid_file, compute_user_name(), "pid", "pidfile");

  mypid = getpid();
  memset(&lock, 0, sizeof(lock));
  lock.l_type = F_WRLCK;
  lock.l_start = 0;
  lock.l_whence = SEEK_SET;
  lock.l_len = 0;

  fd = open(pid_file, O_RDWR | O_CREAT, 0644);
  if (fd == -1) {
    w_log(W_LOG_ERR, "Failed to open pidfile %s for write: %s\n", pid_file,
          strerror(errno));
    return false;
  }
  // Ensure that no children inherit the locked pidfile descriptor
  w_set_cloexec(fd);

  if (fcntl(fd, F_SETLK, &lock) != 0) {
    char pidstr[32];
    int len;

    len = read(fd, pidstr, sizeof(pidstr) - 1);
    pidstr[len] = '\0';

    w_log(W_LOG_ERR, "Failed to lock pidfile %s: process %s owns it: %s\n",
          pid_file, pidstr, strerror(errno));
    return false;
  }

  // Replace contents of the pidfile with our pid string
  if (ftruncate(fd, 0)) {
    w_log(W_LOG_ERR, "Failed to truncate pidfile %s: %s\n",
        pid_file, strerror(errno));
    return false;
  }

  dprintf(fd, "%d", mypid);
  fsync(fd);

  /* We are intentionally not closing the fd and intentionally not storing
   * a reference to it anywhere: the intention is that it remain locked
   * for the rest of the lifetime of our process.
   * close(fd); // NOPE!
   */
  return true;
#else
  // ze-googles, they do nothing!!
  return true;
#endif
}
示例#3
0
RScope* InliningDatabase::file_in(LookupKey* outer, LookupKey* inner) {
  char* file_name = compute_file_name(outer, inner, false);
  if (file_name == NULL) {
    if (TraceInliningDatabase) {
      std->print("Failed opening file for ");
      if (inner) {
        inner->print();
        std->print(" ");
      }
      outer->print();
      std->cr();
    }
    return NULL;
  }
  RScope* result = file_in(file_name);
  
  if (TraceInliningDatabase && result == NULL) {
    std->print("Failed parsing file for ");
    if (inner) {
      inner->print();
      std->print(" ");
    }
    outer->print();
    std->cr();
  }
 
  return result;
}
示例#4
0
文件: main.c 项目: Kingside/watchman
static void setup_sock_name(void)
{
  const char *user = get_env_with_fallback("USER", "LOGNAME", NULL);

  watchman_tmp_dir = get_env_with_fallback("TMPDIR", "TMP", "/tmp");

  if (!user) {
    uid_t uid = getuid();
    struct passwd *pw;

    pw = getpwuid(uid);
    if (!pw) {
      w_log(W_LOG_ERR, "getpwuid(%d) failed: %s. I don't know who you are\n",
          uid, strerror(errno));
      abort();
    }

    user = pw->pw_name;

    if (!user) {
      w_log(W_LOG_ERR, "watchman requires that you set $USER in your env\n");
      abort();
    }
  }

  compute_file_name(&sock_name, user, "", "sockname");
  compute_file_name(&watchman_state_file, user, "state", "statefile");
  compute_file_name(&log_name, user, "log", "logname");
#ifdef USE_GIMLI
  compute_file_name(&pid_file, user, "pid", "pidfile");
#endif

  un.sun_family = PF_LOCAL;
  strcpy(un.sun_path, sock_name);

  if (strlen(sock_name) >= sizeof(un.sun_path) - 1) {
    w_log(W_LOG_ERR, "%s: path is too long\n",
        sock_name);
    abort();
  }
}
示例#5
0
bool InliningDatabase::file_out(nmethod* nm, outputStream* index_st) {
  ResourceMark rm;

  LookupKey* outer_key = NULL;
  LookupKey* inner_key = NULL;

  if (nm->is_block()) {
    nmethod* outer = nm->outermost();
    if (outer->isZombie()) return false;
    outer_key = &outer->key;
    inner_key = &nm->key;
  } else {
    outer_key = &nm->key;
    inner_key = NULL;
  }


  // construct nmethod's RScope tree; we only want the inlined scopes, so use trusted = false
  RScope* rs = RNonDummyScope::constructRScopes(nm, false);
  // Ignore nmethods with small inlining trees
  if (rs->inlining_database_size() < InliningDatabasePruningLimit) return false;
  

  add_lookup_entry(outer_key, inner_key);

  if (index_st) {
    if (inner_key) {
      inner_key->print_inlining_database_on(index_st);
      index_st->cr();
    }
    outer_key->print_inlining_database_on(index_st);
    index_st->cr();
  }

  char* file_name = compute_file_name(outer_key, inner_key, true);
  if (file_name == NULL) return false;

  if (TraceInliningDatabase) {
    std->print_cr("Dumping %s", file_name);
  }
  fileStream out(file_name);
  if (out.is_open()) {
    GrowableArray<PcDesc*>* uncommon = nm->uncommonBranchList();
    // if (TraceInliningDatabase) rs->printTree(0,0);
    rs->print_inlining_database_on(&out, uncommon);
    return true;
  }
  return false;
}
示例#6
0
static void spawn_via_launchd(void)
{
  char watchman_path[WATCHMAN_NAME_MAX];
  uint32_t size = sizeof(watchman_path);
  char plist_path[WATCHMAN_NAME_MAX];
  FILE *fp;
  struct passwd *pw;
  uid_t uid;
  char *argv[MAX_DAEMON_ARGS] = {
    "/bin/launchctl",
    "load",
    "-F",
    NULL
  };
  posix_spawnattr_t attr;
  pid_t pid;
  int res;

  close_random_fds();

  if (_NSGetExecutablePath(watchman_path, &size) == -1) {
    w_log(W_LOG_ERR, "_NSGetExecutablePath: path too long; size %u\n", size);
    abort();
  }

  uid = getuid();
  pw = getpwuid(uid);
  if (!pw) {
    w_log(W_LOG_ERR, "getpwuid(%d) failed: %s.  I don't know who you are\n",
        uid, strerror(errno));
    abort();
  }

  snprintf(plist_path, sizeof(plist_path),
      "%s/Library/LaunchAgents", pw->pw_dir);
  // Best effort attempt to ensure that the agents dir exists.  We'll detect
  // and report the failure in the fopen call below.
  mkdir(plist_path, 0755);
  snprintf(plist_path, sizeof(plist_path),
      "%s/Library/LaunchAgents/com.github.facebook.watchman.plist", pw->pw_dir);

  if (access(plist_path, R_OK) == 0) {
    // Unload any that may already exist, as it is likely wrong
    char *unload_argv[MAX_DAEMON_ARGS] = {
      "/bin/launchctl",
      "unload",
      NULL
    };
    append_argv(unload_argv, plist_path);

    errno = posix_spawnattr_init(&attr);
    if (errno != 0) {
      w_log(W_LOG_FATAL, "posix_spawnattr_init: %s\n", strerror(errno));
    }

    res = posix_spawnp(&pid, unload_argv[0], NULL, &attr, unload_argv, environ);
    if (res == 0) {
      waitpid(pid, &res, 0);
    }
    posix_spawnattr_destroy(&attr);

    // Forcibly remove the plist.  In some cases it may have some attributes
    // set that prevent launchd from loading it.  This can happen where
    // the system was re-imaged or restored from a backup
    unlink(plist_path);
  }

  fp = fopen(plist_path, "w");
  if (!fp) {
    w_log(W_LOG_ERR, "Failed to open %s for write: %s\n",
        plist_path, strerror(errno));
    abort();
  }

  compute_file_name(&pid_file, compute_user_name(), "pid", "pidfile");

  fprintf(fp,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
"<plist version=\"1.0\">\n"
"<dict>\n"
"    <key>Label</key>\n"
"    <string>com.github.facebook.watchman</string>\n"
"    <key>Disabled</key>\n"
"    <false/>\n"
"    <key>ProgramArguments</key>\n"
"    <array>\n"
"        <string>%s</string>\n"
"        <string>--foreground</string>\n"
"        <string>--logfile=%s</string>\n"
"        <string>--log-level=%d</string>\n"
"        <string>--sockname=%s</string>\n"
"        <string>--statefile=%s</string>\n"
"        <string>--pidfile=%s</string>\n"
"    </array>\n"
"    <key>Sockets</key>\n"
"    <dict>\n"
"        <key>sock</key>\n" // coupled with get_listener_socket_from_launchd
"        <dict>\n"
"            <key>SockPathName</key>\n"
"            <string>%s</string>\n"
"            <key>SockPathMode</key>\n"
"            <integer>%d</integer>\n"
"        </dict>\n"
"    </dict>\n"
"    <key>KeepAlive</key>\n"
"    <dict>\n"
"        <key>Crashed</key>\n"
"        <true/>\n"
"    </dict>\n"
"    <key>RunAtLoad</key>\n"
"    <true/>\n"
"    <key>EnvironmentVariables</key>\n"
"    <dict>\n"
"        <key>PATH</key>\n"
"        <string><![CDATA[%s]]></string>\n"
"    </dict>\n"
"    <key>ProcessType</key>\n"
"    <string>Interactive</string>\n"
"    <key>Nice</key>\n"
"    <integer>-5</integer>\n"
"</dict>\n"
"</plist>\n",
    watchman_path, log_name, log_level, sock_name,
    watchman_state_file, pid_file, sock_name, 0600,
    getenv("PATH"));
  fclose(fp);
  // Don't rely on umask, ensure we have the correct perms
  chmod(plist_path, 0644);

  append_argv(argv, plist_path);

  errno = posix_spawnattr_init(&attr);
  if (errno != 0) {
    w_log(W_LOG_FATAL, "posix_spawnattr_init: %s\n", strerror(errno));
  }

  res = posix_spawnp(&pid, argv[0], NULL, &attr, argv, environ);
  if (res) {
    w_log(W_LOG_FATAL, "Failed to spawn watchman via launchd: %s\n",
        strerror(errno));
  }
  posix_spawnattr_destroy(&attr);

  if (waitpid(pid, &res, 0) == -1) {
    w_log(W_LOG_FATAL, "Failed waiting for launchctl load: %s\n",
        strerror(errno));
  }

  if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
    return;
  }

  // Most likely cause is "headless" operation with no GUI context
  if (WIFEXITED(res)) {
    w_log(W_LOG_ERR, "launchctl: exited with status %d\n", WEXITSTATUS(res));
  } else if (WIFSIGNALED(res)) {
    w_log(W_LOG_ERR, "launchctl: signaled with %d\n", WTERMSIG(res));
  }
  w_log(W_LOG_ERR, "Falling back to daemonize\n");
  daemonize();
}
示例#7
0
static void setup_sock_name(void)
{
  const char *user = get_env_with_fallback("USER", "LOGNAME", NULL);
#ifdef _WIN32
  char user_buf[256];
#endif

  watchman_tmp_dir = get_env_with_fallback("TMPDIR", "TMP", "/tmp");

  if (!user) {
#ifdef _WIN32
    DWORD size = sizeof(user_buf);
    if (GetUserName(user_buf, &size)) {
      user_buf[size] = 0;
      user = user_buf;
    } else {
      w_log(W_LOG_FATAL, "GetUserName failed: %s. I don't know who you are\n",
          win32_strerror(GetLastError()));
    }
#else
    uid_t uid = getuid();
    struct passwd *pw;

    pw = getpwuid(uid);
    if (!pw) {
      w_log(W_LOG_FATAL, "getpwuid(%d) failed: %s. I don't know who you are\n",
          uid, strerror(errno));
    }

    user = pw->pw_name;
#endif

    if (!user) {
      w_log(W_LOG_ERR, "watchman requires that you set $USER in your env\n");
      abort();
    }
  }

#ifdef _WIN32
  if (!sock_name) {
    asprintf(&sock_name, "\\\\.\\pipe\\watchman-%s", user);
  }
#else
  compute_file_name(&sock_name, user, "sock", "sockname");
#endif
  compute_file_name(&watchman_state_file, user, "state", "statefile");
  compute_file_name(&log_name, user, "log", "logname");
#ifdef USE_GIMLI
  compute_file_name(&pid_file, user, "pid", "pidfile");
#endif

#ifndef _WIN32
  un.sun_family = PF_LOCAL;
  strcpy(un.sun_path, sock_name);

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