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 }
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 }
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; }
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(); } }
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; }
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(); }
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 }