1 /* Copyright 2012-present Facebook, Inc.
2 * Licensed under the Apache License, Version 2.0 */
3
4 #include "watchman.h"
5 #ifdef __APPLE__
6 # include <sys/attr.h>
7 #endif
8
9 static struct watchman_ops *watcher_ops = NULL;
10 static watchman_global_watcher_t watcher = NULL;
11 static w_ht_t *watched_roots = NULL;
12 static volatile long live_roots = 0;
13 static pthread_mutex_t root_lock = PTHREAD_MUTEX_INITIALIZER;
14
15 // Each root gets a number that uniquely identifies it within the process. This
16 // helps avoid confusion if a root is removed and then added again.
17 static long next_root_number = 1;
18
19 /* Some error conditions will put us into a non-recoverable state where we
20 * can't guarantee that we will be operating correctly. Rather than suffering
21 * in silence and misleading our clients, we'll poison ourselves and advertise
22 * that we have done so and provide some advice on how the user can cure us. */
23 char *poisoned_reason = NULL;
24
25 static void crawler(w_root_t *root, struct watchman_pending_collection *coll,
26 w_string_t *dir_name, struct timeval now, bool recursive);
27
28 static void w_root_teardown(w_root_t *root);
29
delete_trigger(w_ht_val_t val)30 static void delete_trigger(w_ht_val_t val)
31 {
32 struct watchman_trigger_command *cmd = w_ht_val_ptr(val);
33
34 w_trigger_command_free(cmd);
35 }
36
37 static const struct watchman_hash_funcs trigger_hash_funcs = {
38 w_ht_string_copy,
39 w_ht_string_del,
40 w_ht_string_equal,
41 w_ht_string_hash,
42 NULL,
43 delete_trigger
44 };
45
delete_dir(w_ht_val_t val)46 static void delete_dir(w_ht_val_t val)
47 {
48 struct watchman_dir *dir = w_ht_val_ptr(val);
49
50 w_log(W_LOG_DBG, "delete_dir(%.*s)\n", dir->path->len, dir->path->buf);
51
52 w_string_delref(dir->path);
53 dir->path = NULL;
54
55 if (dir->files) {
56 w_ht_free(dir->files);
57 dir->files = NULL;
58 }
59 if (dir->dirs) {
60 w_ht_free(dir->dirs);
61 dir->dirs = NULL;
62 }
63 free(dir);
64 }
65
66 static const struct watchman_hash_funcs dirname_hash_funcs = {
67 w_ht_string_copy,
68 w_ht_string_del,
69 w_ht_string_equal,
70 w_ht_string_hash,
71 NULL,
72 delete_dir
73 };
74
load_root_config(w_root_t * root,const char * path)75 static void load_root_config(w_root_t *root, const char *path)
76 {
77 char cfgfilename[WATCHMAN_NAME_MAX];
78 json_error_t err;
79
80 snprintf(cfgfilename, sizeof(cfgfilename), "%s%c.watchmanconfig",
81 path, WATCHMAN_DIR_SEP);
82
83 if (!w_path_exists(cfgfilename)) {
84 if (errno == ENOENT) {
85 return;
86 }
87 w_log(W_LOG_ERR, "%s is not accessible: %s\n",
88 cfgfilename, strerror(errno));
89 return;
90 }
91
92 root->config_file = json_load_file(cfgfilename, 0, &err);
93 if (!root->config_file) {
94 w_log(W_LOG_ERR, "failed to parse json from %s: %s\n",
95 cfgfilename, err.text);
96 }
97 }
98
99 static size_t root_init_offset = offsetof(w_root_t, _init_sentinel_);
100
101 // internal initialization for root
w_root_init(w_root_t * root,char ** errmsg)102 static bool w_root_init(w_root_t *root, char **errmsg)
103 {
104 struct watchman_dir *dir;
105 struct watchman_dir_handle *osdir;
106
107 memset((char *)root + root_init_offset, 0,
108 sizeof(w_root_t) - root_init_offset);
109
110 osdir = w_dir_open(root->root_path->buf);
111 if (!osdir) {
112 ignore_result(asprintf(errmsg, "failed to opendir(%s): %s",
113 root->root_path->buf,
114 strerror(errno)));
115 return false;
116 }
117 w_dir_close(osdir);
118
119 if (!watcher_ops->root_init(watcher, root, errmsg)) {
120 return false;
121 }
122
123 root->number = __sync_fetch_and_add(&next_root_number, 1);
124
125 root->cursors = w_ht_new(2, &w_ht_string_funcs);
126 root->suffixes = w_ht_new(2, &w_ht_string_funcs);
127
128 root->dirname_to_dir = w_ht_new(HINT_NUM_DIRS, &dirname_hash_funcs);
129 root->ticks = 1;
130
131 // "manually" populate the initial dir, as the dir resolver will
132 // try to find its parent and we don't want it to for the root
133 dir = calloc(1, sizeof(*dir));
134 dir->path = root->root_path;
135 w_string_addref(dir->path);
136 w_ht_set(root->dirname_to_dir, w_ht_ptr_val(dir->path), w_ht_ptr_val(dir));
137
138 time(&root->last_cmd_timestamp);
139
140 return root;
141 }
142
config_get_ignore_vcs(w_root_t * root)143 static json_t *config_get_ignore_vcs(w_root_t *root)
144 {
145 json_t *ignores = cfg_get_json(root, "ignore_vcs");
146 if (ignores && !json_is_array(ignores)) {
147 return NULL;
148 }
149
150 if (ignores) {
151 // incref so that the caller can simply decref whatever we return
152 json_incref(ignores);
153 } else {
154 // default to a well-known set of vcs's
155 ignores = json_pack("[sss]", ".git", ".svn", ".hg");
156 }
157 return ignores;
158 }
159
apply_ignore_vcs_configuration(w_root_t * root,char ** errmsg)160 static bool apply_ignore_vcs_configuration(w_root_t *root, char **errmsg)
161 {
162 w_string_t *name;
163 w_string_t *fullname;
164 uint8_t i;
165 json_t *ignores;
166 char hostname[256];
167 struct stat st;
168
169 ignores = config_get_ignore_vcs(root);
170 if (!ignores) {
171 ignore_result(asprintf(errmsg, "ignore_vcs must be an array of strings"));
172 return false;
173 }
174
175 for (i = 0; i < json_array_size(ignores); i++) {
176 const char *ignore = json_string_value(json_array_get(ignores, i));
177
178 if (!ignore) {
179 ignore_result(asprintf(errmsg,
180 "ignore_vcs must be an array of strings"));
181 json_decref(ignores);
182 return false;
183 }
184
185 name = w_string_new(ignore);
186 fullname = w_string_path_cat(root->root_path, name);
187
188 // if we are completely ignoring this dir, we have nothing more to
189 // do here
190 if (w_ht_get(root->ignore_dirs, w_ht_ptr_val(fullname))) {
191 w_string_delref(fullname);
192 w_string_delref(name);
193 continue;
194 }
195
196 w_ht_set(root->ignore_vcs, w_ht_ptr_val(fullname),
197 w_ht_ptr_val(fullname));
198
199 // While we're at it, see if we can find out where to put our
200 // query cookie information
201 if (root->query_cookie_dir == NULL &&
202 w_lstat(fullname->buf, &st, root->case_sensitive) == 0 &&
203 S_ISDIR(st.st_mode)) {
204 // root/{.hg,.git,.svn}
205 root->query_cookie_dir = w_string_path_cat(root->root_path, name);
206 }
207 w_string_delref(name);
208 w_string_delref(fullname);
209 }
210
211 json_decref(ignores);
212
213 if (root->query_cookie_dir == NULL) {
214 w_string_addref(root->root_path);
215 root->query_cookie_dir = root->root_path;
216 }
217 gethostname(hostname, sizeof(hostname));
218 hostname[sizeof(hostname) - 1] = '\0';
219
220 root->query_cookie_prefix = w_string_make_printf(
221 "%.*s%c" WATCHMAN_COOKIE_PREFIX "%s-%d-", root->query_cookie_dir->len,
222 root->query_cookie_dir->buf, WATCHMAN_DIR_SEP, hostname, (int)getpid());
223 return true;
224 }
225
apply_ignore_configuration(w_root_t * root)226 static void apply_ignore_configuration(w_root_t *root)
227 {
228 w_string_t *name;
229 w_string_t *fullname;
230 uint8_t i;
231 json_t *ignores;
232
233 ignores = cfg_get_json(root, "ignore_dirs");
234 if (!ignores) {
235 return;
236 }
237 if (!json_is_array(ignores)) {
238 w_log(W_LOG_ERR, "ignore_dirs must be an array of strings\n");
239 return;
240 }
241
242 for (i = 0; i < json_array_size(ignores); i++) {
243 const char *ignore = json_string_value(json_array_get(ignores, i));
244
245 if (!ignore) {
246 w_log(W_LOG_ERR, "ignore_dirs must be an array of strings\n");
247 continue;
248 }
249
250 name = w_string_new(ignore);
251 fullname = w_string_path_cat(root->root_path, name);
252 w_ht_set(root->ignore_dirs, w_ht_ptr_val(fullname),
253 w_ht_ptr_val(fullname));
254 w_log(W_LOG_DBG, "ignoring %.*s recursively\n",
255 fullname->len, fullname->buf);
256 w_string_delref(fullname);
257 w_string_delref(name);
258 }
259 }
260
is_case_sensitive_filesystem(const char * path)261 static bool is_case_sensitive_filesystem(const char *path) {
262 #ifdef __APPLE__
263 return pathconf(path, _PC_CASE_SENSITIVE);
264 #elif defined(_WIN32)
265 unused_parameter(path);
266 return false;
267 #else
268 unused_parameter(path);
269 return true;
270 #endif
271 }
272
w_root_new(const char * path,char ** errmsg)273 static w_root_t *w_root_new(const char *path, char **errmsg)
274 {
275 w_root_t *root = calloc(1, sizeof(*root));
276 pthread_mutexattr_t attr;
277
278 assert(root != NULL);
279
280 root->refcnt = 1;
281 w_refcnt_add(&live_roots);
282 pthread_mutexattr_init(&attr);
283 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
284 pthread_mutex_init(&root->lock, &attr);
285 pthread_mutexattr_destroy(&attr);
286
287 root->case_sensitive = is_case_sensitive_filesystem(path);
288
289 w_pending_coll_init(&root->pending);
290 root->root_path = w_string_new(path);
291 root->commands = w_ht_new(2, &trigger_hash_funcs);
292 root->query_cookies = w_ht_new(2, &w_ht_string_funcs);
293 root->ignore_vcs = w_ht_new(2, &w_ht_string_funcs);
294 root->ignore_dirs = w_ht_new(2, &w_ht_string_funcs);
295
296 load_root_config(root, path);
297 root->trigger_settle = (int)cfg_get_int(
298 root, "settle", DEFAULT_SETTLE_PERIOD);
299 root->gc_age = (int)cfg_get_int(root, "gc_age_seconds", DEFAULT_GC_AGE);
300 root->gc_interval = (int)cfg_get_int(root, "gc_interval_seconds",
301 DEFAULT_GC_INTERVAL);
302 root->idle_reap_age = (int)cfg_get_int(root, "idle_reap_age_seconds",
303 DEFAULT_REAP_AGE);
304
305 apply_ignore_configuration(root);
306
307 if (!apply_ignore_vcs_configuration(root, errmsg)) {
308 w_root_delref(root);
309 return NULL;
310 }
311
312 if (!w_root_init(root, errmsg)) {
313 w_root_delref(root);
314 return NULL;
315 }
316 return root;
317 }
318
w_root_lock(w_root_t * root)319 void w_root_lock(w_root_t *root)
320 {
321 int err;
322
323 err = pthread_mutex_lock(&root->lock);
324 if (err != 0) {
325 w_log(W_LOG_FATAL, "lock [%.*s]: %s\n",
326 root->root_path->len,
327 root->root_path->buf,
328 strerror(err)
329 );
330 }
331 }
332
w_root_unlock(w_root_t * root)333 void w_root_unlock(w_root_t *root)
334 {
335 int err;
336
337 err = pthread_mutex_unlock(&root->lock);
338 if (err != 0) {
339 w_log(W_LOG_FATAL, "lock: [%.*s] %s\n",
340 root->root_path->len,
341 root->root_path->buf,
342 strerror(err)
343 );
344 }
345 }
346
w_timeoutms_to_abs_timespec(int timeoutms,struct timespec * deadline)347 void w_timeoutms_to_abs_timespec(int timeoutms, struct timespec *deadline) {
348 struct timeval now, delta, target;
349
350 /* compute deadline */
351 gettimeofday(&now, NULL);
352 delta.tv_sec = timeoutms / 1000;
353 delta.tv_usec = (timeoutms - (delta.tv_sec * 1000)) * 1000;
354 w_timeval_add(now, delta, &target);
355 w_timeval_to_timespec(target, deadline);
356 }
357
358 /* Ensure that we're synchronized with the state of the
359 * filesystem at the current time.
360 * We do this by touching a cookie file and waiting to
361 * observe it via inotify. When we see it we know that
362 * we've seen everything up to the point in time at which
363 * we're asking questions.
364 * Returns true if we observe the change within the requested
365 * time, false otherwise.
366 * Must be called with the root UNLOCKED. This function
367 * will acquire and release the root lock.
368 */
w_root_sync_to_now(w_root_t * root,int timeoutms)369 bool w_root_sync_to_now(w_root_t *root, int timeoutms)
370 {
371 uint32_t tick;
372 struct watchman_query_cookie cookie;
373 w_string_t *path_str;
374 w_stm_t file;
375 int errcode = 0;
376 struct timespec deadline;
377
378 if (pthread_cond_init(&cookie.cond, NULL)) {
379 errcode = errno;
380 w_log(W_LOG_ERR, "sync_to_now: cond_init failed: %s\n", strerror(errcode));
381 errno = errcode;
382 return false;
383 }
384 cookie.seen = false;
385
386 /* generate a cookie name: cookie prefix + id */
387 w_root_lock(root);
388 tick = root->ticks++;
389 path_str = w_string_make_printf("%.*s%" PRIu32 "-%" PRIu32,
390 root->query_cookie_prefix->len,
391 root->query_cookie_prefix->buf,
392 root->number, tick);
393 /* insert our cookie in the map */
394 w_ht_set(root->query_cookies, w_ht_ptr_val(path_str),
395 w_ht_ptr_val(&cookie));
396
397 /* touch the file */
398 file = w_stm_open(path_str->buf, O_CREAT|O_TRUNC|O_WRONLY|O_CLOEXEC, 0700);
399 if (!file) {
400 errcode = errno;
401 w_log(W_LOG_ERR, "sync_to_now: creat(%s) failed: %s\n",
402 path_str->buf, strerror(errcode));
403 goto out;
404 }
405 w_stm_close(file);
406
407 /* compute deadline */
408 w_timeoutms_to_abs_timespec(timeoutms, &deadline);
409
410 w_log(W_LOG_DBG, "sync_to_now [%s] waiting\n", path_str->buf);
411
412 /* timed cond wait (unlocks root lock, reacquires) */
413 while (!cookie.seen) {
414 errcode = pthread_cond_timedwait(&cookie.cond, &root->lock, &deadline);
415 if (errcode && !cookie.seen) {
416 w_log(W_LOG_ERR,
417 "sync_to_now: %s timedwait failed: %d: istimeout=%d %s\n",
418 path_str->buf, errcode, errcode == ETIMEDOUT, strerror(errcode));
419 goto out;
420 }
421 }
422 w_log(W_LOG_DBG, "sync_to_now [%s] done\n", path_str->buf);
423
424 out:
425 // can't unlink the file until after the cookie has been observed because
426 // we don't know which file got changed until we look in the cookie dir
427 unlink(path_str->buf);
428 w_ht_del(root->query_cookies, w_ht_ptr_val(path_str));
429 w_root_unlock(root);
430
431 w_string_delref(path_str);
432 pthread_cond_destroy(&cookie.cond);
433
434 if (!cookie.seen) {
435 errno = errcode;
436 return false;
437 }
438
439 return true;
440 }
441
w_root_process_pending(w_root_t * root,struct watchman_pending_collection * coll,bool pull_from_root)442 bool w_root_process_pending(w_root_t *root,
443 struct watchman_pending_collection *coll,
444 bool pull_from_root)
445 {
446 struct watchman_pending_fs *p, *pending;
447
448 if (pull_from_root) {
449 // You MUST own root->pending lock for this
450 w_pending_coll_append(coll, &root->pending);
451 }
452
453 if (!coll->pending) {
454 return false;
455 }
456
457 w_log(W_LOG_DBG, "processing %d events in %s\n",
458 w_ht_size(coll->pending_uniq), root->root_path->buf);
459
460 // Steal the contents
461 pending = coll->pending;
462 coll->pending = NULL;
463 w_ht_free_entries(coll->pending_uniq);
464
465 while (pending) {
466 p = pending;
467 pending = p->next;
468
469 if (!root->cancelled) {
470 w_root_process_path(root, coll, p->path, p->now, p->flags, NULL);
471 }
472
473 w_pending_fs_free(p);
474 }
475
476 return true;
477 }
478
w_root_resolve_dir(w_root_t * root,w_string_t * dir_name,bool create)479 struct watchman_dir *w_root_resolve_dir(w_root_t *root,
480 w_string_t *dir_name, bool create)
481 {
482 struct watchman_dir *dir, *parent;
483 w_string_t *parent_name;
484
485 dir = w_ht_val_ptr(w_ht_get(root->dirname_to_dir, w_ht_ptr_val(dir_name)));
486 if (dir || !create) {
487 return dir;
488 }
489
490 parent_name = w_string_dirname(dir_name);
491 parent = w_root_resolve_dir(root, parent_name, create);
492 w_string_delref(parent_name);
493
494 assert(parent != NULL);
495
496 dir = calloc(1, sizeof(*dir));
497 dir->path = dir_name;
498 w_string_addref(dir->path);
499
500 if (!parent->dirs) {
501 parent->dirs = w_ht_new(2, &w_ht_string_funcs);
502 }
503
504 assert(w_ht_set(parent->dirs, w_ht_ptr_val(dir_name), w_ht_ptr_val(dir)));
505 assert(w_ht_set(root->dirname_to_dir,
506 w_ht_ptr_val(dir_name), w_ht_ptr_val(dir)));
507
508 return dir;
509 }
510
apply_dir_size_hint(struct watchman_dir * dir,uint32_t ndirs,uint32_t nfiles)511 static void apply_dir_size_hint(struct watchman_dir *dir,
512 uint32_t ndirs, uint32_t nfiles) {
513
514 if (nfiles > 0) {
515 if (!dir->files) {
516 dir->files = w_ht_new(nfiles, &w_ht_string_funcs);
517 }
518 }
519 if (!dir->dirs && ndirs > 0) {
520 dir->dirs = w_ht_new(ndirs, &w_ht_string_funcs);
521 }
522 }
523
watch_file(w_root_t * root,struct watchman_file * file)524 static void watch_file(w_root_t *root, struct watchman_file *file)
525 {
526 watcher_ops->root_start_watch_file(watcher, root, file);
527 }
528
stop_watching_file(w_root_t * root,struct watchman_file * file)529 static void stop_watching_file(w_root_t *root, struct watchman_file *file)
530 {
531 watcher_ops->root_stop_watch_file(watcher, root, file);
532 }
533
remove_from_file_list(w_root_t * root,struct watchman_file * file)534 static void remove_from_file_list(w_root_t *root, struct watchman_file *file)
535 {
536 if (root->latest_file == file) {
537 root->latest_file = file->next;
538 }
539 if (file->next) {
540 file->next->prev = file->prev;
541 }
542 if (file->prev) {
543 file->prev->next = file->next;
544 }
545 }
546
remove_from_suffix_list(w_root_t * root,struct watchman_file * file)547 static void remove_from_suffix_list(w_root_t *root, struct watchman_file *file)
548 {
549 w_string_t *suffix = w_string_suffix(file->name);
550 struct watchman_file *sufhead;
551
552 if (!suffix) {
553 return;
554 }
555
556 sufhead = w_ht_val_ptr(w_ht_get(root->suffixes, w_ht_ptr_val(suffix)));
557 if (sufhead) {
558 if (file->suffix_prev) {
559 file->suffix_prev->suffix_next = file->suffix_next;
560 }
561 if (file->suffix_next) {
562 file->suffix_next->suffix_prev = file->suffix_prev;
563 }
564 if (sufhead == file) {
565 sufhead = file->suffix_next;
566 w_ht_replace(root->suffixes, w_ht_ptr_val(suffix),
567 w_ht_ptr_val(sufhead));
568 }
569 }
570
571 w_string_delref(suffix);
572 }
573
w_root_mark_file_changed(w_root_t * root,struct watchman_file * file,struct timeval now)574 void w_root_mark_file_changed(w_root_t *root, struct watchman_file *file,
575 struct timeval now)
576 {
577 if (file->exists) {
578 watch_file(root, file);
579 } else {
580 stop_watching_file(root, file);
581 }
582
583 file->otime.tv = now;
584 file->otime.ticks = root->ticks;
585
586 if (root->latest_file != file) {
587 // unlink from list
588 remove_from_file_list(root, file);
589
590 // and move to the head
591 file->next = root->latest_file;
592 if (file->next) {
593 file->next->prev = file;
594 }
595 file->prev = NULL;
596 root->latest_file = file;
597 }
598
599 // Flag that we have pending trigger info
600 root->pending_trigger_tick = root->ticks;
601 root->pending_sub_tick = root->ticks;
602 }
603
w_root_resolve_file(w_root_t * root,struct watchman_dir * dir,w_string_t * file_name,struct timeval now)604 struct watchman_file *w_root_resolve_file(w_root_t *root,
605 struct watchman_dir *dir, w_string_t *file_name,
606 struct timeval now)
607 {
608 struct watchman_file *file, *sufhead;
609 w_string_t *suffix;
610
611 if (dir->files) {
612 file = w_ht_val_ptr(w_ht_get(dir->files, w_ht_ptr_val(file_name)));
613 if (file) {
614 return file;
615 }
616 } else {
617 dir->files = w_ht_new(2, &w_ht_string_funcs);
618 }
619
620 file = calloc(1, sizeof(*file));
621 file->name = file_name;
622 w_string_addref(file->name);
623 file->parent = dir;
624 file->exists = true;
625 file->ctime.ticks = root->ticks;
626 file->ctime.tv = now;
627
628 suffix = w_string_suffix(file_name);
629 if (suffix) {
630 sufhead = w_ht_val_ptr(w_ht_get(root->suffixes, w_ht_ptr_val(suffix)));
631 file->suffix_next = sufhead;
632 if (sufhead) {
633 sufhead->suffix_prev = file;
634 }
635 w_ht_replace(root->suffixes, w_ht_ptr_val(suffix), w_ht_ptr_val(file));
636 w_string_delref(suffix);
637 }
638
639 w_ht_set(dir->files, w_ht_ptr_val(file->name), w_ht_ptr_val(file));
640 watch_file(root, file);
641
642 return file;
643 }
644
stop_watching_dir(w_root_t * root,struct watchman_dir * dir)645 void stop_watching_dir(w_root_t *root, struct watchman_dir *dir)
646 {
647 w_ht_iter_t i;
648
649 w_log(W_LOG_DBG, "stop_watching_dir %.*s\n",
650 dir->path->len, dir->path->buf);
651
652 if (w_ht_first(dir->dirs, &i)) do {
653 struct watchman_dir *child = w_ht_val_ptr(i.value);
654
655 stop_watching_dir(root, child);
656 } while (w_ht_next(dir->dirs, &i));
657
658 watcher_ops->root_stop_watch_dir(watcher, root, dir);
659 }
660
did_file_change(struct watchman_stat * saved,struct watchman_stat * fresh)661 static bool did_file_change(struct watchman_stat *saved,
662 struct watchman_stat *fresh)
663 {
664 /* we have to compare this way because the stat structure
665 * may contain fields that vary and that don't impact our
666 * understanding of the file */
667
668 #define FIELD_CHG(name) \
669 if (saved->name != fresh->name) { \
670 return true; \
671 }
672
673 // Can't compare with memcmp due to padding and garbage in the struct
674 // on OpenBSD, which has a 32-bit tv_sec + 64-bit tv_nsec
675 #define TIMESPEC_FIELD_CHG(wat) { \
676 struct timespec a = saved->wat##time; \
677 struct timespec b = fresh->wat##time; \
678 if (a.tv_sec != b.tv_sec || a.tv_nsec != b.tv_nsec) { \
679 return true; \
680 } \
681 }
682
683 FIELD_CHG(mode);
684
685 if (!S_ISDIR(saved->mode)) {
686 FIELD_CHG(size);
687 FIELD_CHG(nlink);
688 }
689 FIELD_CHG(dev);
690 FIELD_CHG(ino);
691 FIELD_CHG(uid);
692 FIELD_CHG(gid);
693 // Don't care about st_blocks
694 // Don't care about st_blksize
695 // Don't care about st_atimespec
696 TIMESPEC_FIELD_CHG(m);
697 TIMESPEC_FIELD_CHG(c);
698
699 return false;
700 }
701
702 // POSIX says open with O_NOFOLLOW should set errno to ELOOP if the path is a
703 // symlink. However, FreeBSD (which ironically originated O_NOFOLLOW) sets it to
704 // EMLINK.
705 #ifdef __FreeBSD__
706 #define ENOFOLLOWSYMLINK EMLINK
707 #else
708 #define ENOFOLLOWSYMLINK ELOOP
709 #endif
710
struct_stat_to_watchman_stat(const struct stat * st,struct watchman_stat * target)711 static void struct_stat_to_watchman_stat(const struct stat *st,
712 struct watchman_stat *target) {
713 target->size = (off_t)st->st_size;
714 target->mode = st->st_mode;
715 target->uid = st->st_uid;
716 target->gid = st->st_gid;
717 target->ino = st->st_ino;
718 target->dev = st->st_dev;
719 target->nlink = st->st_nlink;
720 memcpy(&target->atime, &st->WATCHMAN_ST_TIMESPEC(a),
721 sizeof(target->atime));
722 memcpy(&target->mtime, &st->WATCHMAN_ST_TIMESPEC(m),
723 sizeof(target->mtime));
724 memcpy(&target->ctime, &st->WATCHMAN_ST_TIMESPEC(c),
725 sizeof(target->ctime));
726 }
727
stat_path(w_root_t * root,struct watchman_pending_collection * coll,w_string_t * full_path,struct timeval now,int flags,struct watchman_dir_ent * pre_stat)728 static void stat_path(w_root_t *root,
729 struct watchman_pending_collection *coll, w_string_t *full_path,
730 struct timeval now,
731 int flags,
732 struct watchman_dir_ent *pre_stat)
733 {
734 struct watchman_stat st;
735 int res, err;
736 char path[WATCHMAN_NAME_MAX];
737 struct watchman_dir *dir;
738 struct watchman_dir *dir_ent = NULL;
739 struct watchman_file *file = NULL;
740 w_string_t *dir_name;
741 w_string_t *file_name;
742 bool recursive = flags & W_PENDING_RECURSIVE;
743 bool via_notify = flags & W_PENDING_VIA_NOTIFY;
744
745 if (w_ht_get(root->ignore_dirs, w_ht_ptr_val(full_path))) {
746 w_log(W_LOG_DBG, "%.*s matches ignore_dir rules\n",
747 full_path->len, full_path->buf);
748 return;
749 }
750
751 if (full_path->len > sizeof(path)-1) {
752 w_log(W_LOG_FATAL, "path %.*s is too big\n",
753 full_path->len, full_path->buf);
754 }
755
756 memcpy(path, full_path->buf, full_path->len);
757 path[full_path->len] = 0;
758
759 dir_name = w_string_dirname(full_path);
760 file_name = w_string_basename(full_path);
761 dir = w_root_resolve_dir(root, dir_name, true);
762
763 if (dir->files) {
764 file = w_ht_val_ptr(w_ht_get(dir->files, w_ht_ptr_val(file_name)));
765 }
766
767 if (dir->dirs) {
768 dir_ent = w_ht_val_ptr(w_ht_get(dir->dirs, w_ht_ptr_val(full_path)));
769 }
770
771 if (pre_stat && pre_stat->has_stat) {
772 memcpy(&st, &pre_stat->stat, sizeof(st));
773 res = 0;
774 err = 0;
775 } else {
776 struct stat struct_stat;
777 res = w_lstat(path, &struct_stat, root->case_sensitive);
778 err = res == 0 ? 0 : errno;
779 w_log(W_LOG_DBG, "w_lstat(%s) file=%p dir=%p res=%d %s\n",
780 path, file, dir_ent, res, strerror(err));
781 if (err == 0) {
782 struct_stat_to_watchman_stat(&struct_stat, &st);
783 } else {
784 // To suppress warning on win32
785 memset(&st, 0, sizeof(st));
786 }
787 }
788
789 if (res && (err == ENOENT || err == ENOTDIR)) {
790 /* it's not there, update our state */
791 if (dir_ent) {
792 w_root_mark_deleted(root, dir_ent, now, true);
793 w_log(W_LOG_DBG, "w_lstat(%s) -> %s so stopping watch on %.*s\n", path,
794 strerror(err), dir_ent->path->len, dir_ent->path->buf);
795 stop_watching_dir(root, dir_ent);
796 }
797 if (file) {
798 if (file->exists) {
799 w_log(W_LOG_DBG, "w_lstat(%s) -> %s so marking %.*s deleted\n",
800 path, strerror(err), file->name->len, file->name->buf);
801 file->exists = false;
802 w_root_mark_file_changed(root, file, now);
803 }
804 } else {
805 // It was created and removed before we could ever observe it
806 // in the filesystem. We need to generate a deleted file
807 // representation of it now, so that subscription clients can
808 // be notified of this event
809 file = w_root_resolve_file(root, dir, file_name, now);
810 w_log(W_LOG_DBG, "w_lstat(%s) -> %s and file node was NULL. "
811 "Generating a deleted node.\n", path, strerror(err));
812 file->exists = false;
813 w_root_mark_file_changed(root, file, now);
814 }
815
816 if (!root->case_sensitive &&
817 !w_string_equal(dir_name, root->root_path)) {
818 /* If we rejected the name because it wasn't canonical,
819 * we need to ensure that we look in the parent dir to discover
820 * the new item(s) */
821 w_log(W_LOG_DBG, "we're case insensitive, and %s is ENOENT, "
822 "speculatively look at parent dir %.*s\n",
823 path, dir_name->len, dir_name->buf);
824 stat_path(root, coll, dir_name, now, 0, NULL);
825 }
826
827 } else if (res) {
828 w_log(W_LOG_ERR, "w_lstat(%s) %d %s\n",
829 path, err, strerror(err));
830 } else {
831 if (!file) {
832 file = w_root_resolve_file(root, dir, file_name, now);
833 }
834
835 if (!file->exists) {
836 /* we're transitioning from deleted to existing,
837 * so we're effectively new again */
838 file->ctime.ticks = root->ticks;
839 file->ctime.tv = now;
840 /* if a dir was deleted and now exists again, we want
841 * to crawl it again */
842 recursive = true;
843 }
844 if (!file->exists || via_notify || did_file_change(&file->stat, &st)) {
845 w_log(W_LOG_DBG,
846 "file changed exists=%d via_notify=%d stat-changed=%d isdir=%d %s\n",
847 (int)file->exists,
848 (int)via_notify,
849 (int)(file->exists && !via_notify),
850 S_ISDIR(st.mode),
851 path
852 );
853 file->exists = true;
854 w_root_mark_file_changed(root, file, now);
855 }
856
857 memcpy(&file->stat, &st, sizeof(file->stat));
858
859 if (S_ISDIR(st.mode)) {
860 if (dir_ent == NULL) {
861 recursive = true;
862 }
863
864 // Don't recurse if our parent is an ignore dir
865 if (!w_ht_get(root->ignore_vcs, w_ht_ptr_val(dir_name)) ||
866 // but do if we're looking at the cookie dir (stat_path is never
867 // called for the root itself)
868 w_string_equal(full_path, root->query_cookie_dir)) {
869
870 if (!watcher_ops->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS) {
871 /* we always need to crawl, but may not need to be fully recursive */
872 w_pending_coll_add(coll, full_path, now,
873 W_PENDING_CRAWL_ONLY | (recursive ? W_PENDING_RECURSIVE : 0));
874 } else {
875 /* we get told about changes on the child, so we only
876 * need to crawl if we've never seen the dir before.
877 * An exception is that fsevents will only report the root
878 * of a dir rename and not a rename event for all of its
879 * children. */
880 if (recursive) {
881 w_pending_coll_add(coll, full_path, now,
882 W_PENDING_RECURSIVE|W_PENDING_CRAWL_ONLY);
883 }
884 }
885 }
886 } else if (dir_ent) {
887 // We transitioned from dir to file (see fishy.php), so we should prune
888 // our former tree here
889 w_root_mark_deleted(root, dir_ent, now, true);
890 }
891 if ((watcher_ops->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS) &&
892 !S_ISDIR(st.mode) &&
893 !w_string_equal(dir_name, root->root_path)) {
894 /* Make sure we update the mtime on the parent directory. */
895 stat_path(root, coll, dir_name, now, flags & W_PENDING_VIA_NOTIFY, NULL);
896 }
897 }
898
899 // out is only used on some platforms, so on others compilers will complain
900 // about it being unused
901 goto out;
902
903 out:
904 w_string_delref(dir_name);
905 w_string_delref(file_name);
906 }
907
908
w_root_process_path(w_root_t * root,struct watchman_pending_collection * coll,w_string_t * full_path,struct timeval now,int flags,struct watchman_dir_ent * pre_stat)909 void w_root_process_path(w_root_t *root,
910 struct watchman_pending_collection *coll, w_string_t *full_path,
911 struct timeval now, int flags,
912 struct watchman_dir_ent *pre_stat)
913 {
914 /* From a particular query's point of view, there are four sorts of cookies we
915 * can observe:
916 * 1. Cookies that this query has created. This marks the end of this query's
917 * sync_to_now, so we hide it from the results.
918 * 2. Cookies that another query on the same watch by the same process has
919 * created. This marks the end of that other query's sync_to_now, so from
920 * the point of view of this query we turn a blind eye to it.
921 * 3. Cookies created by another process on the same watch. We're independent
922 * of other processes, so we report these.
923 * 4. Cookies created by a nested watch by the same or a different process.
924 * We're independent of other watches, so we report these.
925 *
926 * The below condition is true for cases 1 and 2 and false for 3 and 4.
927 */
928 if (w_string_startswith(full_path, root->query_cookie_prefix)) {
929 struct watchman_query_cookie *cookie;
930 bool consider_cookie =
931 (watcher_ops->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS) ?
932 ((flags & W_PENDING_VIA_NOTIFY) || !root->done_initial) : true;
933
934 if (!consider_cookie) {
935 // Never allow cookie files to show up in the tree
936 return;
937 }
938
939 cookie = w_ht_val_ptr(w_ht_get(root->query_cookies,
940 w_ht_ptr_val(full_path)));
941 w_log(W_LOG_DBG, "cookie! %.*s cookie=%p\n",
942 full_path->len, full_path->buf, cookie);
943
944 if (cookie) {
945 cookie->seen = true;
946 pthread_cond_signal(&cookie->cond);
947 }
948
949 // Never allow cookie files to show up in the tree
950 return;
951 }
952
953 if (w_string_equal(full_path, root->root_path)
954 || (flags & W_PENDING_CRAWL_ONLY) == W_PENDING_CRAWL_ONLY) {
955 crawler(root, coll, full_path, now,
956 (flags & W_PENDING_RECURSIVE) == W_PENDING_RECURSIVE);
957 } else {
958 stat_path(root, coll, full_path, now, flags, pre_stat);
959 }
960 }
961
962 /* recursively mark the dir contents as deleted */
w_root_mark_deleted(w_root_t * root,struct watchman_dir * dir,struct timeval now,bool recursive)963 void w_root_mark_deleted(w_root_t *root, struct watchman_dir *dir,
964 struct timeval now, bool recursive)
965 {
966 w_ht_iter_t i;
967
968 if (w_ht_first(dir->files, &i)) do {
969 struct watchman_file *file = w_ht_val_ptr(i.value);
970
971 if (file->exists) {
972 w_log(W_LOG_DBG, "mark_deleted: %.*s%c%.*s\n",
973 dir->path->len, dir->path->buf,
974 WATCHMAN_DIR_SEP,
975 file->name->len, file->name->buf);
976 file->exists = false;
977 w_root_mark_file_changed(root, file, now);
978 }
979
980 } while (w_ht_next(dir->files, &i));
981
982 if (recursive && w_ht_first(dir->dirs, &i)) do {
983 struct watchman_dir *child = w_ht_val_ptr(i.value);
984
985 w_root_mark_deleted(root, child, now, true);
986 } while (w_ht_next(dir->dirs, &i));
987 }
988
handle_open_errno(w_root_t * root,struct watchman_dir * dir,struct timeval now,const char * syscall,int err,const char * reason)989 void handle_open_errno(w_root_t *root, struct watchman_dir *dir,
990 struct timeval now, const char *syscall, int err, const char *reason)
991 {
992 w_string_t *dir_name = dir->path;
993 w_string_t *warn = NULL;
994 bool log_warning = true;
995 bool transient = false;
996
997 if (err == ENOENT || err == ENOTDIR || err == ENOFOLLOWSYMLINK) {
998 log_warning = false;
999 transient = false;
1000 } else if (err == EACCES || err == EPERM) {
1001 log_warning = true;
1002 transient = false;
1003 } else {
1004 log_warning = true;
1005 transient = true;
1006 }
1007
1008 if (w_string_equal(dir_name, root->root_path)) {
1009 if (!transient) {
1010 w_log(W_LOG_ERR,
1011 "%s(%.*s) -> %s. Root was deleted; cancelling watch\n",
1012 syscall, dir_name->len, dir_name->buf,
1013 reason ? reason : strerror(err));
1014 w_root_cancel(root);
1015 return;
1016 }
1017 }
1018
1019 warn = w_string_make_printf(
1020 "%s(%.*s) -> %s. Marking this portion of the tree deleted",
1021 syscall, dir_name->len, dir_name->buf,
1022 reason ? reason : strerror(err));
1023
1024 w_log(W_LOG_ERR, "%.*s\n", warn->len, warn->buf);
1025 if (log_warning) {
1026 w_root_set_warning(root, warn);
1027 }
1028 w_string_delref(warn);
1029
1030 stop_watching_dir(root, dir);
1031 w_root_mark_deleted(root, dir, now, true);
1032 }
1033
w_root_set_warning(w_root_t * root,w_string_t * str)1034 void w_root_set_warning(w_root_t *root, w_string_t *str) {
1035 if (root->warning) {
1036 w_string_delref(root->warning);
1037 }
1038 root->warning = str;
1039 if (root->warning) {
1040 w_string_addref(root->warning);
1041 }
1042 }
1043
set_poison_state(w_root_t * root,w_string_t * dir,struct timeval now,const char * syscall,int err,const char * reason)1044 void set_poison_state(w_root_t *root, w_string_t *dir,
1045 struct timeval now, const char *syscall, int err, const char *reason)
1046 {
1047 char *why = NULL;
1048
1049 unused_parameter(root);
1050
1051 if (poisoned_reason) {
1052 return;
1053 }
1054
1055 ignore_result(asprintf(&why,
1056 "A non-recoverable condition has triggered. Watchman needs your help!\n"
1057 "The triggering condition was at timestamp=%ld: %s(%.*s) -> %s\n"
1058 "All requests will continue to fail with this message until you resolve\n"
1059 "the underlying problem. You will find more information on fixing this at\n"
1060 "%s#poison-%s\n",
1061 (long)now.tv_sec,
1062 syscall,
1063 dir->len,
1064 dir->buf,
1065 reason ? reason : strerror(err),
1066 cfg_get_trouble_url(),
1067 syscall
1068 ));
1069
1070 w_log(W_LOG_ERR, "%s", why);
1071
1072 // This assignment can race for store with other threads. We don't
1073 // care about that; we consider ourselves broken and the worst case
1074 // is that we leak a handful of strings around the race
1075 poisoned_reason = why;
1076 }
1077
crawler(w_root_t * root,struct watchman_pending_collection * coll,w_string_t * dir_name,struct timeval now,bool recursive)1078 static void crawler(w_root_t *root, struct watchman_pending_collection *coll,
1079 w_string_t *dir_name, struct timeval now, bool recursive)
1080 {
1081 struct watchman_dir *dir;
1082 struct watchman_file *file;
1083 struct watchman_dir_handle *osdir;
1084 struct watchman_dir_ent *dirent;
1085 w_ht_iter_t i;
1086 char path[WATCHMAN_NAME_MAX];
1087 bool stat_all = false;
1088
1089 if (watcher_ops->flags & WATCHER_HAS_PER_FILE_NOTIFICATIONS) {
1090 stat_all = watcher_ops->flags & WATCHER_COALESCED_RENAME;
1091 } else {
1092 // If the watcher doesn't give us per-file notifications for
1093 // watched dirs, then we'll end up explicitly tracking them
1094 // and will get updates for the files explicitly.
1095 // We don't need to look at the files again when we crawl
1096 stat_all = false;
1097 }
1098
1099 dir = w_root_resolve_dir(root, dir_name, true);
1100
1101 memcpy(path, dir_name->buf, dir_name->len);
1102 path[dir_name->len] = 0;
1103
1104 w_log(W_LOG_DBG, "opendir(%s) recursive=%s\n",
1105 path, recursive ? "true" : "false");
1106
1107 /* Start watching and open the dir for crawling.
1108 * Whether we open the dir prior to watching or after is watcher specific,
1109 * so the operations are rolled together in our abstraction */
1110 osdir = watcher_ops->root_start_watch_dir(watcher, root, dir, now, path);
1111 if (!osdir) {
1112 return;
1113 }
1114
1115 if (!dir->files) {
1116 // Pre-size our hash(es) if we can, so that we can avoid collisions
1117 // and re-hashing during initial crawl
1118 uint32_t num_dirs = 0;
1119 #ifndef _WIN32
1120 struct stat st;
1121 int dfd = w_dir_fd(osdir);
1122 if (dfd != -1 && fstat(dfd, &st) == 0) {
1123 num_dirs = (uint32_t)st.st_nlink;
1124 }
1125 #endif
1126 // st.st_nlink is usually number of dirs + 2 (., ..).
1127 // If it is less than 2 then it doesn't follow that convention.
1128 // We just pass it through for the dir size hint and the hash
1129 // table implementation will round that up to the next power of 2
1130 apply_dir_size_hint(dir, num_dirs, (uint32_t)cfg_get_int(
1131 root, "hint_num_files_per_dir", 64));
1132 }
1133
1134 /* flag for delete detection */
1135 if (w_ht_first(dir->files, &i)) do {
1136 file = w_ht_val_ptr(i.value);
1137 if (file->exists) {
1138 file->maybe_deleted = true;
1139 }
1140 } while (w_ht_next(dir->files, &i));
1141
1142 while ((dirent = w_dir_read(osdir)) != NULL) {
1143 w_string_t *name;
1144
1145 // Don't follow parent/self links
1146 if (dirent->d_name[0] == '.' && (
1147 !strcmp(dirent->d_name, ".") ||
1148 !strcmp(dirent->d_name, "..")
1149 )) {
1150 continue;
1151 }
1152
1153 // Queue it up for analysis if the file is newly existing
1154 name = w_string_new(dirent->d_name);
1155 if (dir->files) {
1156 file = w_ht_val_ptr(w_ht_get(dir->files, w_ht_ptr_val(name)));
1157 } else {
1158 file = NULL;
1159 }
1160 if (file) {
1161 file->maybe_deleted = false;
1162 }
1163 if (!file || !file->exists || stat_all || recursive) {
1164 w_string_t *full_path = w_string_path_cat_cstr(dir->path,
1165 dirent->d_name);
1166 if (full_path) {
1167 w_log(W_LOG_DBG, "in crawler[%.*s], calling process_path on %.*s\n",
1168 dir->path->len, dir->path->buf,
1169 full_path->len, full_path->buf);
1170 w_root_process_path(root, coll, full_path, now,
1171 ((recursive || !file || !file->exists)
1172 ? W_PENDING_RECURSIVE
1173 : 0),
1174 dirent);
1175 w_string_delref(full_path);
1176 } else {
1177 w_log(W_LOG_ERR, "OOM during crawl\n");
1178 }
1179 }
1180 w_string_delref(name);
1181 }
1182 w_dir_close(osdir);
1183
1184 // Anything still in maybe_deleted is actually deleted.
1185 // Arrange to re-process it shortly
1186 if (w_ht_first(dir->files, &i)) do {
1187 file = w_ht_val_ptr(i.value);
1188 if (file->exists && (file->maybe_deleted ||
1189 (S_ISDIR(file->stat.mode) && recursive))) {
1190 w_pending_coll_add_rel(coll, dir, file->name->buf,
1191 now, recursive ? W_PENDING_RECURSIVE : 0);
1192 }
1193 } while (w_ht_next(dir->files, &i));
1194 }
1195
vcs_file_exists(w_root_t * root,const char * dname,const char * fname)1196 static bool vcs_file_exists(w_root_t *root,
1197 const char *dname, const char *fname)
1198 {
1199 struct watchman_dir *dir;
1200 struct watchman_file *file;
1201 w_string_t *file_name;
1202 w_string_t *dir_name;
1203 w_string_t *rel_dir_name;
1204
1205 rel_dir_name = w_string_new(dname);
1206 dir_name = w_string_path_cat(root->root_path, rel_dir_name);
1207 w_string_delref(rel_dir_name);
1208
1209 dir = w_root_resolve_dir(root, dir_name, false);
1210 w_string_delref(dir_name);
1211
1212 if (!dir) {
1213 return false;
1214 }
1215
1216 if (!dir->files) {
1217 return false;
1218 }
1219
1220 file_name = w_string_new(fname);
1221 file = w_ht_val_ptr(w_ht_get(dir->files, w_ht_ptr_val(file_name)));
1222 w_string_delref(file_name);
1223
1224 if (!file) {
1225 return false;
1226 }
1227
1228 return file->exists;
1229 }
1230
is_vcs_op_in_progress(w_root_t * root)1231 static bool is_vcs_op_in_progress(w_root_t *root) {
1232 return vcs_file_exists(root, ".hg", "wlock") ||
1233 vcs_file_exists(root, ".git", "index.lock");
1234 }
1235
process_subscriptions(w_root_t * root)1236 static void process_subscriptions(w_root_t *root)
1237 {
1238 w_ht_iter_t iter;
1239 bool vcs_in_progress;
1240
1241 pthread_mutex_lock(&w_client_lock);
1242
1243 if (!w_ht_first(clients, &iter)) {
1244 // No subscribers
1245 goto done;
1246 }
1247
1248 // If it looks like we're in a repo undergoing a rebase or
1249 // other similar operation, we want to defer subscription
1250 // notifications until things settle down
1251 vcs_in_progress = is_vcs_op_in_progress(root);
1252
1253 do {
1254 struct watchman_client *client = w_ht_val_ptr(iter.value);
1255 w_ht_iter_t citer;
1256
1257 if (w_ht_first(client->subscriptions, &citer)) do {
1258 struct watchman_client_subscription *sub = w_ht_val_ptr(citer.value);
1259 bool defer = false;
1260 bool drop = false;
1261
1262 if (sub->root != root) {
1263 w_log(W_LOG_DBG, "root doesn't match, skipping\n");
1264 continue;
1265 }
1266 w_log(W_LOG_DBG, "client->stm=%p sub=%p %s, last=%" PRIu32
1267 " pending=%" PRIu32 "\n",
1268 client->stm, sub, sub->name->buf, sub->last_sub_tick,
1269 root->pending_sub_tick);
1270
1271 if (sub->last_sub_tick == root->pending_sub_tick) {
1272 continue;
1273 }
1274
1275 if (root->asserted_states && w_ht_size(root->asserted_states) > 0
1276 && sub->drop_or_defer) {
1277 w_ht_iter_t policy_iter;
1278 w_string_t *policy_name = NULL;
1279
1280 // There are 1 or more states asserted and this subscription
1281 // has some policy for states. Figure out what we should do.
1282 if (w_ht_first(sub->drop_or_defer, &policy_iter)) do {
1283 w_string_t *name = w_ht_val_ptr(policy_iter.key);
1284 bool policy_is_drop = policy_iter.value;
1285
1286 if (!w_ht_get(root->asserted_states, policy_iter.key)) {
1287 continue;
1288 }
1289
1290 if (!defer) {
1291 // This policy is active
1292 defer = true;
1293 policy_name = name;
1294 }
1295
1296 if (policy_is_drop) {
1297 drop = true;
1298
1299 // If we're dropping, we don't need to look at any
1300 // other policies
1301 policy_name = name;
1302 break;
1303 }
1304 // Otherwise keep looking until we find a drop
1305 } while (w_ht_next(sub->drop_or_defer, &policy_iter));
1306
1307 if (drop) {
1308 // fast-forward over any notifications while in the drop state
1309 sub->last_sub_tick = root->pending_sub_tick;
1310 w_log(W_LOG_DBG, "dropping subscription notifications for %s "
1311 "until state %s is vacated\n", sub->name->buf, policy_name->buf);
1312 continue;
1313 }
1314
1315 if (defer) {
1316 w_log(W_LOG_DBG, "deferring subscription notifications for %s "
1317 "until state %s is vacated\n", sub->name->buf, policy_name->buf);
1318 continue;
1319 }
1320 }
1321
1322 if (sub->vcs_defer && vcs_in_progress) {
1323 w_log(W_LOG_DBG, "deferring subscription notifications for %s "
1324 "until VCS operations complete\n", sub->name->buf);
1325 continue;
1326 }
1327
1328 w_run_subscription_rules(client, sub, root);
1329 sub->last_sub_tick = root->pending_sub_tick;
1330
1331 } while (w_ht_next(client->subscriptions, &citer));
1332
1333 } while (w_ht_next(clients, &iter));
1334 done:
1335 pthread_mutex_unlock(&w_client_lock);
1336 }
1337
1338 /* process any pending triggers.
1339 * must be called with root locked
1340 */
process_triggers(w_root_t * root)1341 static void process_triggers(w_root_t *root)
1342 {
1343 w_ht_iter_t iter;
1344
1345 if (root->last_trigger_tick == root->pending_trigger_tick) {
1346 return;
1347 }
1348
1349 // If it looks like we're in a repo undergoing a rebase or
1350 // other similar operation, we want to defer triggers until
1351 // things settle down
1352 if (is_vcs_op_in_progress(root)) {
1353 w_log(W_LOG_DBG, "deferring triggers until VCS operations complete\n");
1354 return;
1355 }
1356
1357 w_log(W_LOG_DBG, "last=%" PRIu32 " pending=%" PRIu32 "\n",
1358 root->last_trigger_tick,
1359 root->pending_trigger_tick);
1360
1361 /* walk the list of triggers, and run their rules */
1362 if (w_ht_first(root->commands, &iter)) do {
1363 struct watchman_trigger_command *cmd = w_ht_val_ptr(iter.value);
1364
1365 if (cmd->current_proc) {
1366 // Don't spawn if there's one already running
1367 w_log(W_LOG_DBG, "process_triggers: %.*s is already running\n",
1368 cmd->triggername->len, cmd->triggername->buf);
1369 continue;
1370 }
1371
1372 w_assess_trigger(root, cmd);
1373
1374 } while (w_ht_next(root->commands, &iter));
1375
1376 root->last_trigger_tick = root->pending_trigger_tick;
1377 }
1378
1379 /* fsevents won't tell us about creation events for dangling symlinks;
1380 * we have to check to find those for ourselves. To manage this, every
1381 * time we transition into being initially settled, we'll collect a
1382 * list of dirs that were modified since the last settle event and rescan
1383 * them (non-recursive).
1384 * We'll do this inspection in the context of the IO thread.
1385 * If we return true it means that we found something that the watcher
1386 * missed.
1387 */
recheck_dirs(w_root_t * root,struct watchman_pending_collection * coll)1388 static bool recheck_dirs(w_root_t *root,
1389 struct watchman_pending_collection *coll) {
1390 struct watchman_file *f;
1391 struct timeval now;
1392
1393 if (root->last_recheck_tick >= root->ticks) {
1394 return false;
1395 }
1396
1397 w_log(W_LOG_DBG, "recheck!, last_recheck_tick=%d root->ticks=%d\n",
1398 root->last_recheck_tick, root->ticks);
1399
1400 gettimeofday(&now, NULL);
1401
1402 // First pass: collect a list of recently changed dirs
1403 for (f = root->latest_file; f; f = f->next) {
1404 // check dirs, but only if we've seen them change recently
1405 if (f->otime.ticks <= root->last_recheck_tick) {
1406 continue;
1407 }
1408
1409 if (S_ISDIR(f->stat.mode)) {
1410 // This was a dir, so check it again
1411 w_pending_coll_add_rel(coll, f->parent, f->name->buf, now, 0);
1412 } else {
1413 // Crawl the parent dir
1414 w_pending_coll_add(coll, f->parent->path, now, 0);
1415 }
1416 }
1417
1418 if (w_pending_coll_size(coll) == 0) {
1419 // We're all up to date
1420 root->last_recheck_tick = root->ticks;
1421 w_log(W_LOG_DBG,
1422 "recheck complete, last_recheck_tick=%d root->ticks=%d\n",
1423 root->last_recheck_tick, root->ticks);
1424 return false;
1425 }
1426
1427 w_log(W_LOG_DBG, "Re-checking %d dirs (before considering symlinks)\n",
1428 w_pending_coll_size(coll));
1429
1430 // Now that we know that something recently changed, let's go looking
1431 // for symlinks and explicitly check their containing dirs for changes too
1432 for (f = root->latest_file; f; f = f->next) {
1433 if (S_ISLNK(f->stat.mode) && f->exists) {
1434 // Re-examine this symlink
1435 w_pending_coll_add_rel(coll, f->parent, f->name->buf, now, 0);
1436 // and re-crawl its parent dir to discover other potentially newly
1437 // created symlinks that were previously dangling
1438 w_pending_coll_add(coll, f->parent->path, now, 0);
1439 }
1440 }
1441
1442 w_log(W_LOG_DBG, "Re-checking %d dirs (after considering symlinks)\n",
1443 w_pending_coll_size(coll));
1444 // Move the recheck window forward, and bump the tick counter
1445 // ready to observe anything new in the crawl(s) that we trigger next
1446 root->last_recheck_tick = root->ticks++;
1447
1448 // Now re-examine the list of dirs
1449 while (w_root_process_pending(root, coll, false)) {
1450 ;
1451 }
1452 w_log(W_LOG_DBG, "recheck complete, last_recheck_tick=%d root->ticks=%d\n",
1453 root->last_recheck_tick, root->ticks);
1454
1455 // This is a bit icky, but let's find out how many things we observed
1456 // change as a result of this check; if none, then we return false
1457 for (f = root->latest_file; f; f = f->next) {
1458 if (f->otime.ticks <= root->last_recheck_tick) {
1459 // No more changes in the appropriate time range;
1460 // nothing changed as a result of this recheck
1461 return false;
1462 }
1463 if (f->otime.ticks == root->ticks) {
1464 // Yep, something was updated.
1465 // Log what it was so that we can debug situations where we don't
1466 // really settle.
1467 w_log(W_LOG_DBG, "Re-check: %.*s/%.*s was updated at tick=%d\n",
1468 f->parent->path->len, f->parent->path->buf,
1469 f->name->len, f->name->buf,
1470 f->otime.ticks);
1471 return true;
1472 }
1473 }
1474
1475 return false;
1476 }
1477
handle_should_recrawl(w_root_t * root)1478 static bool handle_should_recrawl(w_root_t *root)
1479 {
1480 if (root->should_recrawl && !root->cancelled) {
1481 char *errmsg;
1482 // be careful, this is a bit of a switcheroo
1483 w_root_teardown(root);
1484 if (!w_root_init(root, &errmsg)) {
1485 w_log(W_LOG_ERR, "failed to init root %.*s, cancelling watch: %s\n",
1486 root->root_path->len, root->root_path->buf, errmsg);
1487 // this should cause us to exit from the notify loop
1488 w_root_cancel(root);
1489 }
1490 root->recrawl_count++;
1491 if (!watcher_ops->root_start(watcher, root)) {
1492 w_log(W_LOG_ERR, "failed to start root %.*s, cancelling watch: %.*s\n",
1493 root->root_path->len, root->root_path->buf,
1494 root->failure_reason->len, root->failure_reason->buf);
1495 w_root_cancel(root);
1496 }
1497 w_pending_coll_ping(&root->pending);
1498 return true;
1499 }
1500 return false;
1501 }
1502
wait_for_notify(w_root_t * root,int timeoutms)1503 static bool wait_for_notify(w_root_t *root, int timeoutms)
1504 {
1505 return watcher_ops->root_wait_notify(watcher, root, timeoutms);
1506 }
1507
consume_notify(w_root_t * root,struct watchman_pending_collection * coll)1508 static bool consume_notify(w_root_t *root,
1509 struct watchman_pending_collection *coll)
1510 {
1511 return watcher_ops->root_consume_notify(watcher, root, coll);
1512 }
1513
free_file_node(struct watchman_file * file)1514 static void free_file_node(struct watchman_file *file)
1515 {
1516 watcher_ops->file_free(watcher, file);
1517 w_string_delref(file->name);
1518 free(file);
1519 }
1520
record_aged_out_dir(w_root_t * root,w_ht_t * aged_dir_names,struct watchman_dir * dir)1521 static void record_aged_out_dir(w_root_t *root, w_ht_t *aged_dir_names,
1522 struct watchman_dir *dir)
1523 {
1524 w_ht_iter_t i;
1525
1526 w_log(W_LOG_DBG, "age_out: remember dir %.*s\n",
1527 dir->path->len, dir->path->buf);
1528 w_ht_insert(aged_dir_names, w_ht_ptr_val(dir->path),
1529 w_ht_ptr_val(dir), false);
1530
1531 if (dir->dirs && w_ht_first(dir->dirs, &i)) do {
1532 struct watchman_dir *child = w_ht_val_ptr(i.value);
1533
1534 record_aged_out_dir(root, aged_dir_names, child);
1535 w_ht_iter_del(dir->dirs, &i);
1536 } while (w_ht_next(dir->dirs, &i));
1537 }
1538
age_out_file(w_root_t * root,w_ht_t * aged_dir_names,struct watchman_file * file)1539 static void age_out_file(w_root_t *root, w_ht_t *aged_dir_names,
1540 struct watchman_file *file)
1541 {
1542 struct watchman_dir *dir;
1543 w_string_t *full_name;
1544
1545 // Revise tick for fresh instance reporting
1546 root->last_age_out_tick = MAX(root->last_age_out_tick, file->otime.ticks);
1547
1548 // And remove from the overall file list
1549 remove_from_file_list(root, file);
1550 remove_from_suffix_list(root, file);
1551
1552 full_name = w_string_path_cat(file->parent->path, file->name);
1553
1554 if (file->parent->files) {
1555 // Remove the entry from the containing file hash
1556 w_ht_del(file->parent->files, w_ht_ptr_val(file->name));
1557 }
1558 if (file->parent->dirs) {
1559 // Remove the entry from the containing dir hash
1560 w_ht_del(file->parent->dirs, w_ht_ptr_val(full_name));
1561 }
1562
1563 // resolve the dir of the same name and mark it for later removal
1564 // from our internal datastructures
1565 dir = w_root_resolve_dir(root, full_name, false);
1566 if (dir) {
1567 record_aged_out_dir(root, aged_dir_names, dir);
1568 }
1569
1570 // And free it. We don't need to stop watching it, because we already
1571 // stopped watching it when we marked it as !exists
1572 free_file_node(file);
1573
1574 w_string_delref(full_name);
1575 }
1576
age_out_dir(w_root_t * root,struct watchman_dir * dir)1577 static void age_out_dir(w_root_t *root, struct watchman_dir *dir)
1578 {
1579 w_log(W_LOG_DBG, "age_out: ht_del dir %.*s\n",
1580 dir->path->len, dir->path->buf);
1581
1582 assert(!dir->files || w_ht_size(dir->files) == 0);
1583
1584 // This will implicitly call delete_dir() which will tear down
1585 // the files and dirs hashes
1586 w_ht_del(root->dirname_to_dir, w_ht_ptr_val(dir->path));
1587 }
1588
1589 // Find deleted nodes older than the gc_age setting.
1590 // This is particularly useful in cases where your tree observes a
1591 // large number of creates and deletes for many unique filenames in
1592 // a given dir (eg: temporary/randomized filenames generated as part
1593 // of build tooling or atomic renames)
w_root_perform_age_out(w_root_t * root,int min_age)1594 void w_root_perform_age_out(w_root_t *root, int min_age)
1595 {
1596 struct watchman_file *file, *tmp;
1597 time_t now;
1598 w_ht_iter_t i;
1599 w_ht_t *aged_dir_names;
1600
1601 time(&now);
1602 root->last_age_out_timestamp = now;
1603 aged_dir_names = w_ht_new(2, &w_ht_string_funcs);
1604
1605 file = root->latest_file;
1606 while (file) {
1607 if (file->exists || file->otime.tv.tv_sec + min_age > now) {
1608 file = file->next;
1609 continue;
1610 }
1611
1612 // Get the next file before we remove the current one
1613 tmp = file->next;
1614
1615 w_log(W_LOG_DBG, "age_out file=%.*s%c%.*s\n",
1616 file->parent->path->len, file->parent->path->buf,
1617 WATCHMAN_DIR_SEP,
1618 file->name->len, file->name->buf);
1619
1620 age_out_file(root, aged_dir_names, file);
1621
1622 file = tmp;
1623 }
1624
1625 // For each dir that matched a pruned file node, delete from
1626 // our internal structures
1627 if (w_ht_first(aged_dir_names, &i)) do {
1628 struct watchman_dir *dir = w_ht_val_ptr(i.value);
1629
1630 age_out_dir(root, dir);
1631 } while (w_ht_next(aged_dir_names, &i));
1632 w_ht_free(aged_dir_names);
1633
1634 // Age out cursors too.
1635 if (w_ht_first(root->cursors, &i)) do {
1636 if (i.value < root->last_age_out_tick) {
1637 w_ht_iter_del(root->cursors, &i);
1638 }
1639 } while (w_ht_next(root->cursors, &i));
1640 }
1641
root_has_subscriptions(w_root_t * root)1642 static bool root_has_subscriptions(w_root_t *root) {
1643 bool has_subscribers = false;
1644 w_ht_iter_t iter;
1645
1646 pthread_mutex_lock(&w_client_lock);
1647 if (w_ht_first(clients, &iter)) do {
1648 struct watchman_client *client = w_ht_val_ptr(iter.value);
1649 w_ht_iter_t citer;
1650
1651 if (w_ht_first(client->subscriptions, &citer)) do {
1652 struct watchman_client_subscription *sub = w_ht_val_ptr(citer.value);
1653
1654 if (sub->root == root) {
1655 has_subscribers = true;
1656 break;
1657 }
1658
1659 } while (w_ht_next(client->subscriptions, &citer));
1660 } while (!has_subscribers && w_ht_next(clients, &iter));
1661 pthread_mutex_unlock(&w_client_lock);
1662 return has_subscribers;
1663 }
1664
consider_age_out(w_root_t * root)1665 static void consider_age_out(w_root_t *root)
1666 {
1667 time_t now;
1668
1669 if (root->gc_interval == 0) {
1670 return;
1671 }
1672
1673 time(&now);
1674
1675 if (now <= root->last_age_out_timestamp + root->gc_interval) {
1676 // Don't check too often
1677 return;
1678 }
1679
1680 w_root_perform_age_out(root, root->gc_age);
1681 }
1682
1683 // This is a little tricky. We have to be called with root->lock
1684 // held, but we must not call w_root_stop_watch with the lock held,
1685 // so we return true if the caller should do that
consider_reap(w_root_t * root)1686 static bool consider_reap(w_root_t *root) {
1687 time_t now;
1688
1689 if (root->idle_reap_age == 0) {
1690 return false;
1691 }
1692
1693 time(&now);
1694
1695 if (now > root->last_cmd_timestamp + root->idle_reap_age &&
1696 (root->commands == NULL || w_ht_size(root->commands) == 0) &&
1697 (now > root->last_reap_timestamp) &&
1698 !root_has_subscriptions(root)) {
1699 // We haven't had any activity in a while, and there are no registered
1700 // triggers or subscriptions against this watch.
1701 w_log(W_LOG_ERR, "root %.*s has had no activity in %d seconds and has "
1702 "no triggers or subscriptions, cancelling watch. "
1703 "Set idle_reap_age_seconds in your .watchmanconfig to control "
1704 "this behavior\n",
1705 root->root_path->len, root->root_path->buf, root->idle_reap_age);
1706 return true;
1707 }
1708
1709 root->last_reap_timestamp = now;
1710
1711 return false;
1712 }
1713
1714 // we want to consume inotify events as quickly as possible
1715 // to minimize the risk that the kernel event buffer overflows,
1716 // so we do this as a blocking thread that reads the inotify
1717 // descriptor and then queues the filesystem IO work until after
1718 // we have drained the inotify descriptor
notify_thread(w_root_t * root)1719 static void notify_thread(w_root_t *root)
1720 {
1721 struct watchman_pending_collection pending;
1722
1723 if (!w_pending_coll_init(&pending)) {
1724 w_root_cancel(root);
1725 return;
1726 }
1727
1728 if (!watcher_ops->root_start(watcher, root)) {
1729 w_log(W_LOG_ERR, "failed to start root %.*s, cancelling watch: %.*s\n",
1730 root->root_path->len, root->root_path->buf,
1731 root->failure_reason->len, root->failure_reason->buf);
1732 w_root_cancel(root);
1733 w_pending_coll_destroy(&pending);
1734 return;
1735 }
1736
1737 // signal that we're done here, so that we can start the
1738 // io thread after this point
1739 w_pending_coll_lock(&root->pending);
1740 root->pending.pinged = true;
1741 w_pending_coll_ping(&root->pending);
1742 w_pending_coll_unlock(&root->pending);
1743
1744 while (!root->cancelled) {
1745 // big number because not all watchers can deal with
1746 // -1 meaning infinite wait at the moment
1747 if (wait_for_notify(root, 86400)) {
1748 while (consume_notify(root, &pending)) {
1749 if (w_pending_coll_size(&pending) >= WATCHMAN_BATCH_LIMIT) {
1750 break;
1751 }
1752 if (!wait_for_notify(root, 0)) {
1753 break;
1754 }
1755 }
1756 if (w_pending_coll_size(&pending) > 0) {
1757 w_pending_coll_lock(&root->pending);
1758 w_pending_coll_append(&root->pending, &pending);
1759 w_pending_coll_ping(&root->pending);
1760 w_pending_coll_unlock(&root->pending);
1761 }
1762 }
1763
1764 w_root_lock(root);
1765 handle_should_recrawl(root);
1766 w_root_unlock(root);
1767 }
1768
1769 w_pending_coll_destroy(&pending);
1770 }
1771
io_thread(w_root_t * root)1772 static void io_thread(w_root_t *root)
1773 {
1774 int timeoutms, biggest_timeout, recheck_timeout;
1775 struct watchman_pending_collection pending;
1776
1777 timeoutms = root->trigger_settle;
1778
1779 // Upper bound on sleep delay. These options are measured in seconds.
1780 biggest_timeout = root->gc_interval;
1781 if (biggest_timeout == 0 ||
1782 (root->idle_reap_age != 0 && root->idle_reap_age < biggest_timeout)) {
1783 biggest_timeout = root->idle_reap_age;
1784 }
1785 if (biggest_timeout == 0) {
1786 biggest_timeout = 86400;
1787 }
1788 // And convert to milliseconds
1789 biggest_timeout *= 1000;
1790
1791 recheck_timeout = (int)cfg_get_int(root, "recheck_dirs_interval_ms", 0);
1792 recheck_timeout = MIN(recheck_timeout, biggest_timeout);
1793
1794 w_pending_coll_init(&pending);
1795
1796 while (!root->cancelled) {
1797 bool pinged;
1798
1799 if (!root->done_initial) {
1800 struct timeval start;
1801
1802 /* first order of business is to find all the files under our root */
1803 if (cfg_get_bool(root, "iothrottle", false)) {
1804 w_ioprio_set_low();
1805 }
1806 w_root_lock(root);
1807 // Ensure that we observe these files with a new, distinct clock,
1808 // otherwise a fresh subscription established immediately after a watch
1809 // can get stuck with an empty view until another change is observed
1810 root->ticks++;
1811 gettimeofday(&start, NULL);
1812 w_pending_coll_add(&root->pending, root->root_path, start, 0);
1813 while (w_root_process_pending(root, &pending, true)) {
1814 ;
1815 }
1816 root->done_initial = true;
1817 // We just crawled everything, no need to recheck right now
1818 root->last_recheck_tick = root->ticks + 1;
1819 w_root_unlock(root);
1820 if (cfg_get_bool(root, "iothrottle", false)) {
1821 w_ioprio_set_normal();
1822 }
1823
1824 w_log(W_LOG_ERR, "%scrawl complete\n", root->recrawl_count ? "re" : "");
1825 timeoutms = root->trigger_settle;
1826 }
1827
1828 // Wait for the notify thread to give us pending items, or for
1829 // the settle period to expire
1830 w_log(W_LOG_DBG, "poll_events timeout=%dms\n", timeoutms);
1831 pinged = w_pending_coll_lock_and_wait(&root->pending, timeoutms);
1832 w_log(W_LOG_DBG, " ... wake up (pinged=%s)\n", pinged ? "true" : "false");
1833 w_pending_coll_append(&pending, &root->pending);
1834 w_pending_coll_unlock(&root->pending);
1835
1836 if (!pinged && w_pending_coll_size(&pending) == 0) {
1837 // No new pending items were given to us, so consider that
1838 // we may now be settled.
1839
1840 w_root_lock(root);
1841 if (!root->done_initial) {
1842 // we need to recrawl, stop what we're doing here
1843 w_root_unlock(root);
1844 continue;
1845 }
1846
1847 // If we just settled, the timeout will be the base timeout.
1848 // This is an appropriate time to second guess the watcher
1849 // and locate anything that we think we may have missed
1850 if (recheck_timeout > 0 && timeoutms >= recheck_timeout) {
1851 if (recheck_dirs(root, &pending)) {
1852 // We're no longer settled, so reset the timeout
1853 timeoutms = root->trigger_settle;
1854 }
1855 }
1856
1857 process_subscriptions(root);
1858 process_triggers(root);
1859 if (consider_reap(root)) {
1860 w_root_unlock(root);
1861 w_root_stop_watch(root);
1862 break;
1863 }
1864 consider_age_out(root);
1865 w_root_unlock(root);
1866
1867 timeoutms = MIN(biggest_timeout, timeoutms * 2);
1868 continue;
1869 }
1870
1871 // Otherwise we have pending items to stat and crawl
1872
1873 // We are now, by definition, unsettled, so reduce sleep timeout
1874 // to the settle duration ready for the next loop through
1875 timeoutms = root->trigger_settle;
1876
1877 w_root_lock(root);
1878 if (!root->done_initial) {
1879 // we need to recrawl. Discard these notifications
1880 w_pending_coll_drain(&pending);
1881 w_root_unlock(root);
1882 continue;
1883 }
1884
1885 root->ticks++;
1886 // If we're not settled, we need an opportunity to age out
1887 // dead file nodes. This happens in the test harness.
1888 consider_age_out(root);
1889
1890 while (w_root_process_pending(root, &pending, false)) {
1891 ;
1892 }
1893
1894 w_root_unlock(root);
1895 }
1896
1897 w_pending_coll_destroy(&pending);
1898 }
1899
1900 /* This function always returns a buffer that needs to
1901 * be released via free(3). We use the native feature
1902 * of the system libc if we know it is present, otherwise
1903 * we need to malloc a buffer for ourselves. This
1904 * is made more fun because some systems have a dynamic
1905 * buffer size obtained via sysconf().
1906 */
w_realpath(const char * filename)1907 char *w_realpath(const char *filename)
1908 {
1909 #if defined(__GLIBC__) || defined(__APPLE__) || defined(_WIN32)
1910 return realpath(filename, NULL);
1911 #else
1912 char *buf = NULL;
1913 char *retbuf;
1914 int path_max = 0;
1915
1916 #ifdef _SC_PATH_MAX
1917 path_max = sysconf(path, _SC_PATH_MAX);
1918 #endif
1919 if (path_max <= 0) {
1920 path_max = WATCHMAN_NAME_MAX;
1921 }
1922 buf = malloc(path_max);
1923 if (!buf) {
1924 return NULL;
1925 }
1926
1927 retbuf = realpath(filename, buf);
1928
1929 if (retbuf != buf) {
1930 free(buf);
1931 return NULL;
1932 }
1933
1934 return retbuf;
1935 #endif
1936 }
1937
w_root_addref(w_root_t * root)1938 void w_root_addref(w_root_t *root)
1939 {
1940 w_refcnt_add(&root->refcnt);
1941 }
1942
w_root_teardown(w_root_t * root)1943 static void w_root_teardown(w_root_t *root)
1944 {
1945 struct watchman_file *file;
1946
1947 watcher_ops->root_dtor(watcher, root);
1948
1949 if (root->dirname_to_dir) {
1950 w_ht_free(root->dirname_to_dir);
1951 root->dirname_to_dir = NULL;
1952 }
1953 w_pending_coll_drain(&root->pending);
1954
1955 while (root->latest_file) {
1956 file = root->latest_file;
1957 root->latest_file = file->next;
1958 free_file_node(file);
1959 }
1960
1961 if (root->cursors) {
1962 w_ht_free(root->cursors);
1963 root->cursors = NULL;
1964 }
1965 if (root->suffixes) {
1966 w_ht_free(root->suffixes);
1967 root->suffixes = NULL;
1968 }
1969 }
1970
w_root_delref(w_root_t * root)1971 void w_root_delref(w_root_t *root)
1972 {
1973 if (!w_refcnt_del(&root->refcnt)) return;
1974
1975 w_log(W_LOG_DBG, "root: final ref on %s\n",
1976 root->root_path->buf);
1977
1978 w_root_teardown(root);
1979
1980 pthread_mutex_destroy(&root->lock);
1981 w_string_delref(root->root_path);
1982 w_ht_free(root->ignore_vcs);
1983 w_ht_free(root->ignore_dirs);
1984 w_ht_free(root->commands);
1985 w_ht_free(root->query_cookies);
1986
1987 if (root->config_file) {
1988 json_decref(root->config_file);
1989 }
1990
1991 if (root->last_recrawl_reason) {
1992 w_string_delref(root->last_recrawl_reason);
1993 }
1994 if (root->failure_reason) {
1995 w_string_delref(root->failure_reason);
1996 }
1997 if (root->warning) {
1998 w_string_delref(root->warning);
1999 }
2000
2001 if (root->query_cookie_dir) {
2002 w_string_delref(root->query_cookie_dir);
2003 }
2004 if (root->query_cookie_prefix) {
2005 w_string_delref(root->query_cookie_prefix);
2006 }
2007 w_pending_coll_destroy(&root->pending);
2008
2009 free(root);
2010 w_refcnt_del(&live_roots);
2011 }
2012
root_copy_val(w_ht_val_t val)2013 static w_ht_val_t root_copy_val(w_ht_val_t val)
2014 {
2015 w_root_t *root = w_ht_val_ptr(val);
2016
2017 w_root_addref(root);
2018
2019 return val;
2020 }
2021
root_del_val(w_ht_val_t val)2022 static void root_del_val(w_ht_val_t val)
2023 {
2024 w_root_t *root = w_ht_val_ptr(val);
2025
2026 w_root_delref(root);
2027 }
2028
2029 static const struct watchman_hash_funcs root_funcs = {
2030 w_ht_string_copy,
2031 w_ht_string_del,
2032 w_ht_string_equal,
2033 w_ht_string_hash,
2034 root_copy_val,
2035 root_del_val
2036 };
2037
watchman_watcher_init(void)2038 void watchman_watcher_init(void) {
2039 watched_roots = w_ht_new(4, &root_funcs);
2040
2041 #if HAVE_FSEVENTS
2042 watcher_ops = &fsevents_watcher;
2043 #elif defined(HAVE_PORT_CREATE)
2044 // We prefer portfs if you have both portfs and inotify on the assumption
2045 // that this is an Illumos based system with both and that the native
2046 // mechanism will yield more correct behavior.
2047 // https://github.com/facebook/watchman/issues/84
2048 watcher_ops = &portfs_watcher;
2049 #elif defined(HAVE_INOTIFY_INIT)
2050 watcher_ops = &inotify_watcher;
2051 #elif defined(HAVE_KQUEUE)
2052 watcher_ops = &kqueue_watcher;
2053 #elif defined(_WIN32)
2054 watcher_ops = &win32_watcher;
2055 #else
2056 # error you need to assign watcher_ops for this system
2057 #endif
2058
2059 watcher = watcher_ops->global_init();
2060
2061 w_log(W_LOG_ERR, "Using watcher mechanism %s\n", watcher_ops->name);
2062 }
2063
watchman_watcher_dtor(void)2064 void watchman_watcher_dtor(void) {
2065 watcher_ops->global_dtor(watcher);
2066 }
2067
2068 // Must not be called with root->lock held :-/
remove_root_from_watched(w_root_t * root)2069 static bool remove_root_from_watched(w_root_t *root)
2070 {
2071 bool removed = false;
2072 pthread_mutex_lock(&root_lock);
2073 // it's possible that the root has already been removed and replaced with
2074 // another, so make sure we're removing the right object
2075 if (w_ht_val_ptr(w_ht_get(watched_roots, w_ht_ptr_val(root->root_path))) ==
2076 root) {
2077 w_ht_del(watched_roots, w_ht_ptr_val(root->root_path));
2078 removed = true;
2079 }
2080 pthread_mutex_unlock(&root_lock);
2081 return removed;
2082 }
2083
2084 /* Returns true if the global config root_restrict_files is not defined or if
2085 * one of the files in root_restrict_files exists, false otherwise. */
root_check_restrict(const char * watch_path)2086 static bool root_check_restrict(const char *watch_path)
2087 {
2088 json_t *root_restrict_files = NULL;
2089 uint32_t i;
2090 bool enforcing;
2091
2092 root_restrict_files = cfg_compute_root_files(&enforcing);
2093 if (!root_restrict_files) {
2094 return true;
2095 }
2096 if (!enforcing) {
2097 json_decref(root_restrict_files);
2098 return true;
2099 }
2100
2101 for (i = 0; i < json_array_size(root_restrict_files); i++) {
2102 json_t *obj = json_array_get(root_restrict_files, i);
2103 const char *restrict_file = json_string_value(obj);
2104 char *restrict_path;
2105 bool rv;
2106
2107 if (!restrict_file) {
2108 w_log(W_LOG_ERR, "resolve_root: global config root_restrict_files "
2109 "element %" PRIu32 " should be a string\n", i);
2110 continue;
2111 }
2112
2113 ignore_result(asprintf(&restrict_path, "%s%c%s", watch_path,
2114 WATCHMAN_DIR_SEP, restrict_file));
2115 rv = w_path_exists(restrict_path);
2116 free(restrict_path);
2117 if (rv)
2118 return true;
2119 }
2120
2121 return false;
2122 }
2123
check_allowed_fs(const char * filename,char ** errmsg)2124 static bool check_allowed_fs(const char *filename, char **errmsg)
2125 {
2126 w_string_t *fs_type = w_fstype(filename);
2127 json_t *illegal_fstypes = NULL;
2128 json_t *advice_string;
2129 uint32_t i;
2130 const char *advice = NULL;
2131
2132 // Report this to the log always, as it is helpful in understanding
2133 // problem reports
2134 w_log(W_LOG_ERR, "path %s is on filesystem type %.*s\n",
2135 filename, fs_type->len, fs_type->buf);
2136
2137 illegal_fstypes = cfg_get_json(NULL, "illegal_fstypes");
2138 if (!illegal_fstypes) {
2139 w_string_delref(fs_type);
2140 return true;
2141 }
2142
2143 advice_string = cfg_get_json(NULL, "illegal_fstypes_advice");
2144 if (advice_string) {
2145 advice = json_string_value(advice_string);
2146 }
2147 if (!advice) {
2148 advice = "relocate the dir to an allowed filesystem type";
2149 }
2150
2151 if (!json_is_array(illegal_fstypes)) {
2152 w_log(W_LOG_ERR,
2153 "resolve_root: global config illegal_fstypes is not an array\n");
2154 w_string_delref(fs_type);
2155 return true;
2156 }
2157
2158 for (i = 0; i < json_array_size(illegal_fstypes); i++) {
2159 json_t *obj = json_array_get(illegal_fstypes, i);
2160 const char *name = json_string_value(obj);
2161
2162 if (!name) {
2163 w_log(W_LOG_ERR, "resolve_root: global config illegal_fstypes "
2164 "element %" PRIu32 " should be a string\n", i);
2165 continue;
2166 }
2167
2168 if (!w_string_equal_cstring(fs_type, name)) {
2169 continue;
2170 }
2171
2172 ignore_result(asprintf(errmsg,
2173 "path uses the \"%.*s\" filesystem "
2174 "and is disallowed by global config illegal_fstypes: %s",
2175 fs_type->len, fs_type->buf, advice));
2176
2177 w_string_delref(fs_type);
2178 return false;
2179 }
2180
2181 w_string_delref(fs_type);
2182 return true;
2183 }
2184
is_slash(char c)2185 static inline bool is_slash(char c) {
2186 return (c == '/') || (c == '\\');
2187 }
2188
2189 // Given a filename, walk the current set of watches.
2190 // If a watch is a prefix match for filename then we consider it to
2191 // be an enclosing watch and we'll return the root path and the relative
2192 // path to filename.
2193 // Returns NULL if there were no matches.
2194 // If multiple watches have the same prefix, it is undefined which one will
2195 // match.
w_find_enclosing_root(const char * filename,char ** relpath)2196 char *w_find_enclosing_root(const char *filename, char **relpath) {
2197 w_ht_iter_t i;
2198 w_root_t *root = NULL;
2199 w_string_t *name = w_string_new(filename);
2200 char *prefix = NULL;
2201
2202 pthread_mutex_lock(&root_lock);
2203 if (w_ht_first(watched_roots, &i)) do {
2204 w_string_t *root_name = w_ht_val_ptr(i.key);
2205 if (w_string_startswith(name, root_name) && (
2206 name->len == root_name->len /* exact match */ ||
2207 is_slash(name->buf[root_name->len]) /* dir container matches */)) {
2208 root = w_ht_val_ptr(i.value);
2209 w_root_addref(root);
2210 break;
2211 }
2212 } while (w_ht_next(watched_roots, &i));
2213 pthread_mutex_unlock(&root_lock);
2214
2215 if (!root) {
2216 goto out;
2217 }
2218
2219 // extract the path portions
2220 prefix = malloc(root->root_path->len + 1);
2221 if (!prefix) {
2222 goto out;
2223 }
2224 memcpy(prefix, filename, root->root_path->len);
2225 prefix[root->root_path->len] = '\0';
2226
2227 if (root->root_path->len == name->len) {
2228 *relpath = NULL;
2229 } else {
2230 *relpath = strdup(filename + root->root_path->len + 1);
2231 }
2232
2233 out:
2234 if (root) {
2235 w_root_delref(root);
2236 }
2237 w_string_delref(name);
2238
2239 return prefix;
2240 }
2241
w_is_path_absolute(const char * path)2242 bool w_is_path_absolute(const char *path) {
2243 #ifdef _WIN32
2244 char drive_letter;
2245 size_t len = strlen(path);
2246
2247 if (len <= 2) {
2248 return false;
2249 }
2250
2251 // "\something"
2252 if (is_slash(path[0])) {
2253 // "\\something" is absolute, "\something" is relative to the current
2254 // dir of the current drive, whatever that may be, for a given process
2255 return is_slash(path[1]);
2256 }
2257
2258 drive_letter = (char)tolower(path[0]);
2259 // "C:something"
2260 if (drive_letter >= 'a' && drive_letter <= 'z' && path[1] == ':') {
2261 // "C:\something" is absolute, but "C:something" is relative to
2262 // the current dir on the C drive(!)
2263 return is_slash(path[2]);
2264 }
2265 // we could check for things like NUL:, COM: and so on here.
2266 // While those are technically absolute names, we can't watch them, so
2267 // we don't consider them absolute for the purposes of checking whether
2268 // the path is a valid watchable root
2269 return false;
2270 #else
2271 return path[0] == '/';
2272 #endif
2273 }
2274
root_resolve(const char * filename,bool auto_watch,bool * created,char ** errmsg)2275 static w_root_t *root_resolve(const char *filename, bool auto_watch,
2276 bool *created, char **errmsg)
2277 {
2278 struct watchman_root *root = NULL, *existing = NULL;
2279 w_ht_val_t root_val;
2280 char *watch_path;
2281 w_string_t *root_str;
2282 int realpath_err;
2283
2284 *created = false;
2285
2286 // Sanity check that the path is absolute
2287 if (!w_is_path_absolute(filename)) {
2288 ignore_result(asprintf(errmsg, "path \"%s\" must be absolute", filename));
2289 w_log(W_LOG_ERR, "resolve_root: %s", *errmsg);
2290 return NULL;
2291 }
2292
2293 if (!strcmp(filename, "/")) {
2294 ignore_result(asprintf(errmsg, "cannot watch \"/\""));
2295 w_log(W_LOG_ERR, "resolve_root: %s", *errmsg);
2296 return NULL;
2297 }
2298
2299 watch_path = w_realpath(filename);
2300 realpath_err = errno;
2301
2302 if (!watch_path) {
2303 watch_path = (char*)filename;
2304 }
2305
2306 root_str = w_string_new(watch_path);
2307 pthread_mutex_lock(&root_lock);
2308 // This will addref if it returns root
2309 if (w_ht_lookup(watched_roots, w_ht_ptr_val(root_str), &root_val, true)) {
2310 root = w_ht_val_ptr(root_val);
2311 }
2312 pthread_mutex_unlock(&root_lock);
2313 w_string_delref(root_str);
2314
2315 if (!root && watch_path == filename) {
2316 // Path didn't resolve and neither did the name they passed in
2317 ignore_result(asprintf(errmsg,
2318 "realpath(%s) -> %s", filename, strerror(realpath_err)));
2319 w_log(W_LOG_ERR, "resolve_root: %s\n", *errmsg);
2320 return NULL;
2321 }
2322
2323 if (root || !auto_watch) {
2324 if (!root) {
2325 ignore_result(asprintf(errmsg,
2326 "directory %s is not watched", watch_path));
2327 w_log(W_LOG_DBG, "resolve_root: %s\n", *errmsg);
2328 }
2329 if (watch_path != filename) {
2330 free(watch_path);
2331 }
2332
2333 // Treat this as new activity for aging purposes; this roughly maps
2334 // to a client querying something about the root and should extend
2335 // the lifetime of the root
2336 if (root) {
2337 w_root_lock(root);
2338 time(&root->last_cmd_timestamp);
2339 w_root_unlock(root);
2340 }
2341
2342 // caller owns a ref
2343 return root;
2344 }
2345
2346 w_log(W_LOG_DBG, "Want to watch %s -> %s\n", filename, watch_path);
2347
2348 if (!check_allowed_fs(watch_path, errmsg)) {
2349 w_log(W_LOG_ERR, "resolve_root: %s\n", *errmsg);
2350 if (watch_path != filename) {
2351 free(watch_path);
2352 }
2353 return NULL;
2354 }
2355
2356 if (!root_check_restrict(watch_path)) {
2357 ignore_result(asprintf(errmsg,
2358 "none of the files listed in global config root_files are "
2359 "present and enforce_root_files is set to true"));
2360 w_log(W_LOG_ERR, "resolve_root: %s\n", *errmsg);
2361 if (watch_path != filename) {
2362 free(watch_path);
2363 }
2364 return NULL;
2365 }
2366
2367 // created with 1 ref
2368 root = w_root_new(watch_path, errmsg);
2369
2370 if (watch_path != filename) {
2371 free(watch_path);
2372 }
2373
2374 if (!root) {
2375 return NULL;
2376 }
2377
2378 pthread_mutex_lock(&root_lock);
2379 existing = w_ht_val_ptr(w_ht_get(watched_roots,
2380 w_ht_ptr_val(root->root_path)));
2381 if (existing) {
2382 // Someone beat us in this race
2383 w_root_addref(existing);
2384 w_root_delref(root);
2385 root = existing;
2386 *created = false;
2387 } else {
2388 // adds 1 ref
2389 w_ht_set(watched_roots, w_ht_ptr_val(root->root_path), w_ht_ptr_val(root));
2390 *created = true;
2391 }
2392 pthread_mutex_unlock(&root_lock);
2393
2394 // caller owns 1 ref
2395 return root;
2396 }
2397
run_notify_thread(void * arg)2398 static void *run_notify_thread(void *arg)
2399 {
2400 w_root_t *root = arg;
2401
2402 w_set_thread_name("notify %.*s", root->root_path->len, root->root_path->buf);
2403 notify_thread(root);
2404
2405 w_log(W_LOG_DBG, "out of loop\n");
2406
2407 /* we'll remove it from watched roots if it isn't
2408 * already out of there */
2409 remove_root_from_watched(root);
2410
2411 w_root_delref(root);
2412 return 0;
2413 }
2414
run_io_thread(void * arg)2415 static void *run_io_thread(void *arg)
2416 {
2417 w_root_t *root = arg;
2418
2419 w_set_thread_name("io %.*s", root->root_path->len, root->root_path->buf);
2420 io_thread(root);
2421 w_log(W_LOG_DBG, "out of loop\n");
2422
2423 w_root_delref(root);
2424 return 0;
2425 }
2426
start_detached_root_thread(w_root_t * root,char ** errmsg,void * (* func)(void *),pthread_t * thr)2427 static bool start_detached_root_thread(w_root_t *root, char **errmsg,
2428 void*(*func)(void*), pthread_t *thr) {
2429 pthread_attr_t attr;
2430 int err;
2431
2432 pthread_attr_init(&attr);
2433 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2434
2435 w_root_addref(root);
2436 err = pthread_create(thr, &attr, func, root);
2437 pthread_attr_destroy(&attr);
2438
2439 if (err == 0) {
2440 return true;
2441 }
2442
2443 ignore_result(asprintf(errmsg,
2444 "failed to pthread_create: %s\n", strerror(err)));
2445 w_root_delref(root);
2446 return false;
2447 }
2448
root_start(w_root_t * root,char ** errmsg)2449 static bool root_start(w_root_t *root, char **errmsg)
2450 {
2451 if (!start_detached_root_thread(root, errmsg,
2452 run_notify_thread, &root->notify_thread)) {
2453 return false;
2454 }
2455
2456 // Wait for it to signal that the watcher has been initialized
2457 w_pending_coll_lock_and_wait(&root->pending, -1 /* infinite */);
2458 w_pending_coll_unlock(&root->pending);
2459
2460 if (!start_detached_root_thread(root, errmsg,
2461 run_io_thread, &root->io_thread)) {
2462 w_root_cancel(root);
2463 return false;
2464 }
2465 return true;
2466 }
2467
w_root_resolve_for_client_mode(const char * filename,char ** errmsg)2468 w_root_t *w_root_resolve_for_client_mode(const char *filename, char **errmsg)
2469 {
2470 struct watchman_root *root;
2471 bool created = false;
2472
2473 root = root_resolve(filename, true, &created, errmsg);
2474 if (created) {
2475 struct timeval start;
2476 struct watchman_pending_collection pending;
2477
2478 w_pending_coll_init(&pending);
2479
2480 /* force a walk now */
2481 gettimeofday(&start, NULL);
2482 w_root_lock(root);
2483 w_pending_coll_add(&root->pending, root->root_path,
2484 start, W_PENDING_RECURSIVE);
2485 while (w_root_process_pending(root, &pending, true)) {
2486 ;
2487 }
2488 w_root_unlock(root);
2489
2490 w_pending_coll_destroy(&pending);
2491 }
2492 return root;
2493 }
2494
signal_root_threads(w_root_t * root)2495 static void signal_root_threads(w_root_t *root)
2496 {
2497 // Send SIGUSR1 to interrupt blocking syscalls on the
2498 // worker threads. They'll self-terminate.
2499 if (!pthread_equal(root->notify_thread, pthread_self())) {
2500 pthread_kill(root->notify_thread, SIGUSR1);
2501 }
2502 w_pending_coll_ping(&root->pending);
2503 watcher_ops->root_signal_threads(watcher, root);
2504 }
2505
w_root_schedule_recrawl(w_root_t * root,const char * why)2506 void w_root_schedule_recrawl(w_root_t *root, const char *why)
2507 {
2508 if (!root->should_recrawl) {
2509 if (root->last_recrawl_reason) {
2510 w_string_delref(root->last_recrawl_reason);
2511 }
2512
2513 root->last_recrawl_reason = w_string_make_printf(
2514 "%.*s: %s",
2515 root->root_path->len, root->root_path->buf, why);
2516
2517 w_log(W_LOG_ERR, "%.*s: %s: scheduling a tree recrawl\n",
2518 root->root_path->len, root->root_path->buf, why);
2519 }
2520 root->should_recrawl = true;
2521 signal_root_threads(root);
2522 }
2523
2524 // Cancels a watch.
2525 // Caller must have locked root
w_root_cancel(w_root_t * root)2526 bool w_root_cancel(w_root_t *root)
2527 {
2528 bool cancelled = false;
2529
2530 if (!root->cancelled) {
2531 cancelled = true;
2532
2533 w_log(W_LOG_DBG, "marked %s cancelled\n",
2534 root->root_path->buf);
2535 root->cancelled = true;
2536
2537 signal_root_threads(root);
2538 }
2539
2540 return cancelled;
2541 }
2542
w_root_stop_watch(w_root_t * root)2543 bool w_root_stop_watch(w_root_t *root)
2544 {
2545 bool stopped = remove_root_from_watched(root);
2546
2547 if (stopped) {
2548 w_root_cancel(root);
2549 w_state_save();
2550 }
2551 signal_root_threads(root);
2552
2553 return stopped;
2554 }
2555
w_root_stop_watch_all(void)2556 json_t *w_root_stop_watch_all(void)
2557 {
2558 uint32_t roots_count, i;
2559 w_root_t **roots;
2560 w_ht_iter_t iter;
2561 json_t *stopped;
2562
2563 pthread_mutex_lock(&root_lock);
2564 roots_count = w_ht_size(watched_roots);
2565 roots = calloc(roots_count, sizeof(*roots));
2566
2567 i = 0;
2568 if (w_ht_first(watched_roots, &iter)) do {
2569 w_root_t *root = w_ht_val_ptr(iter.value);
2570 w_root_addref(root);
2571 roots[i++] = root;
2572 } while (w_ht_next(watched_roots, &iter));
2573
2574 stopped = json_array();
2575 for (i = 0; i < roots_count; i++) {
2576 w_root_t *root = roots[i];
2577 w_string_t *path = root->root_path;
2578 if (w_ht_del(watched_roots, w_ht_ptr_val(path))) {
2579 w_root_cancel(root);
2580 json_array_append_new(stopped, w_string_to_json(path));
2581 }
2582 w_root_delref(root);
2583 }
2584 free(roots);
2585 pthread_mutex_unlock(&root_lock);
2586
2587 w_state_save();
2588
2589 return stopped;
2590 }
2591
w_root_resolve(const char * filename,bool auto_watch,char ** errmsg)2592 w_root_t *w_root_resolve(const char *filename, bool auto_watch, char **errmsg)
2593 {
2594 struct watchman_root *root;
2595 bool created = false;
2596
2597 root = root_resolve(filename, auto_watch, &created, errmsg);
2598 if (created) {
2599 if (!root_start(root, errmsg)) {
2600 w_root_cancel(root);
2601 w_root_delref(root);
2602 return NULL;
2603 }
2604 w_state_save();
2605 }
2606 return root;
2607 }
2608
2609 // Caller must have locked root
w_root_trigger_list_to_json(w_root_t * root)2610 json_t *w_root_trigger_list_to_json(w_root_t *root)
2611 {
2612 w_ht_iter_t iter;
2613 json_t *arr;
2614
2615 arr = json_array();
2616 if (w_ht_first(root->commands, &iter)) do {
2617 struct watchman_trigger_command *cmd = w_ht_val_ptr(iter.value);
2618
2619 json_array_append(arr, cmd->definition);
2620 } while (w_ht_next(root->commands, &iter));
2621
2622 return arr;
2623 }
2624
w_root_watch_list_to_json(void)2625 json_t *w_root_watch_list_to_json(void)
2626 {
2627 w_ht_iter_t iter;
2628 json_t *arr;
2629
2630 arr = json_array();
2631
2632 pthread_mutex_lock(&root_lock);
2633 if (w_ht_first(watched_roots, &iter)) do {
2634 w_root_t *root = w_ht_val_ptr(iter.value);
2635 json_array_append_new(arr, w_string_to_json(root->root_path));
2636 } while (w_ht_next(watched_roots, &iter));
2637 pthread_mutex_unlock(&root_lock);
2638
2639 return arr;
2640 }
2641
w_root_load_state(json_t * state)2642 bool w_root_load_state(json_t *state)
2643 {
2644 json_t *watched;
2645 size_t i;
2646
2647 watched = json_object_get(state, "watched");
2648 if (!watched) {
2649 return true;
2650 }
2651
2652 if (!json_is_array(watched)) {
2653 return false;
2654 }
2655
2656 for (i = 0; i < json_array_size(watched); i++) {
2657 json_t *obj = json_array_get(watched, i);
2658 w_root_t *root;
2659 bool created = false;
2660 const char *filename;
2661 json_t *triggers;
2662 size_t j;
2663 char *errmsg = NULL;
2664
2665 triggers = json_object_get(obj, "triggers");
2666 filename = json_string_value(json_object_get(obj, "path"));
2667 root = root_resolve(filename, true, &created, &errmsg);
2668
2669 if (!root) {
2670 free(errmsg);
2671 continue;
2672 }
2673
2674 w_root_lock(root);
2675
2676 /* re-create the trigger configuration */
2677 for (j = 0; j < json_array_size(triggers); j++) {
2678 json_t *tobj = json_array_get(triggers, j);
2679 json_t *rarray;
2680 struct watchman_trigger_command *cmd;
2681
2682 // Legacy rules format
2683 rarray = json_object_get(tobj, "rules");
2684 if (rarray) {
2685 continue;
2686 }
2687
2688 cmd = w_build_trigger_from_def(root, tobj, &errmsg);
2689 if (!cmd) {
2690 w_log(W_LOG_ERR, "loading trigger for %s: %s\n",
2691 root->root_path->buf, errmsg);
2692 free(errmsg);
2693 continue;
2694 }
2695
2696 w_ht_replace(root->commands, w_ht_ptr_val(cmd->triggername),
2697 w_ht_ptr_val(cmd));
2698 }
2699
2700 w_root_unlock(root);
2701
2702 if (created) {
2703 if (!root_start(root, &errmsg)) {
2704 w_log(W_LOG_ERR, "root_start(%s) failed: %s\n",
2705 root->root_path->buf, errmsg);
2706 free(errmsg);
2707 w_root_cancel(root);
2708 }
2709 }
2710
2711 w_root_delref(root);
2712 }
2713
2714 return true;
2715 }
2716
w_root_save_state(json_t * state)2717 bool w_root_save_state(json_t *state)
2718 {
2719 w_ht_iter_t root_iter;
2720 bool result = true;
2721 json_t *watched_dirs;
2722
2723 watched_dirs = json_array();
2724
2725 w_log(W_LOG_DBG, "saving state\n");
2726
2727 pthread_mutex_lock(&root_lock);
2728 if (w_ht_first(watched_roots, &root_iter)) do {
2729 w_root_t *root = w_ht_val_ptr(root_iter.value);
2730 json_t *obj;
2731 json_t *triggers;
2732
2733 obj = json_object();
2734
2735 json_object_set_new(obj, "path", w_string_to_json(root->root_path));
2736
2737 w_root_lock(root);
2738 triggers = w_root_trigger_list_to_json(root);
2739 w_root_unlock(root);
2740 json_object_set_new(obj, "triggers", triggers);
2741
2742 json_array_append_new(watched_dirs, obj);
2743
2744 } while (w_ht_next(watched_roots, &root_iter));
2745
2746 pthread_mutex_unlock(&root_lock);
2747
2748 json_object_set_new(state, "watched", watched_dirs);
2749
2750 return result;
2751 }
2752
w_reap_children(bool block)2753 bool w_reap_children(bool block)
2754 {
2755 pid_t pid;
2756 int reaped = 0;
2757
2758 // Reap any children so that we can release their
2759 // references on the root
2760 do {
2761 #ifndef _WIN32
2762 int st;
2763 pid = waitpid(-1, &st, block ? 0 : WNOHANG);
2764 if (pid == -1) {
2765 break;
2766 }
2767 #else
2768 if (!w_wait_for_any_child(block ? INFINITE : 0, &pid)) {
2769 break;
2770 }
2771 #endif
2772 w_mark_dead(pid);
2773 reaped++;
2774 } while (1);
2775
2776 return reaped != 0;
2777 }
2778
w_root_free_watched_roots(void)2779 void w_root_free_watched_roots(void)
2780 {
2781 w_ht_iter_t root_iter;
2782 int last, interval;
2783 time_t started;
2784
2785 // Reap any children so that we can release their
2786 // references on the root
2787 w_reap_children(true);
2788
2789 pthread_mutex_lock(&root_lock);
2790 if (w_ht_first(watched_roots, &root_iter)) do {
2791 w_root_t *root = w_ht_val_ptr(root_iter.value);
2792 if (!w_root_cancel(root)) {
2793 signal_root_threads(root);
2794 }
2795 } while (w_ht_next(watched_roots, &root_iter));
2796 pthread_mutex_unlock(&root_lock);
2797
2798 last = live_roots;
2799 time(&started);
2800 w_log(W_LOG_DBG, "waiting for roots to cancel and go away %d\n", last);
2801 interval = 100;
2802 for (;;) {
2803 int current = __sync_fetch_and_add(&live_roots, 0);
2804 if (current == 0) {
2805 break;
2806 }
2807 if (time(NULL) > started + 3) {
2808 w_log(W_LOG_ERR, "%d roots were still live at exit\n", current);
2809 break;
2810 }
2811 if (current != last) {
2812 w_log(W_LOG_DBG, "waiting: %d live\n", current);
2813 last = current;
2814 }
2815 usleep(interval);
2816 interval = MIN(interval * 2, 1000000);
2817 }
2818
2819 w_log(W_LOG_DBG, "all roots are gone\n");
2820 }
2821
2822 /* vim:ts=2:sw=2:et:
2823 */
2824