Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(419)

Side by Side Diff: runtime/bin/file_system_watcher_macos.cc

Issue 147083015: Fix file-watcher on mac by always starting/stopping through the run-loop thread. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_MACOS) 6 #if defined(TARGET_OS_MACOS)
7 7
8 #include "bin/file_system_watcher.h" 8 #include "bin/file_system_watcher.h"
9 9
10 #include <errno.h> // NOLINT 10 #include <errno.h> // NOLINT
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 uint32_t flags; 48 uint32_t flags;
49 char path[PATH_MAX]; 49 char path[PATH_MAX];
50 } data; 50 } data;
51 uint8_t bytes[PATH_MAX + 8]; 51 uint8_t bytes[PATH_MAX + 8];
52 }; 52 };
53 53
54 class FSEventsWatcher { 54 class FSEventsWatcher {
55 public: 55 public:
56 class Node { 56 class Node {
57 public: 57 public:
58 Node(intptr_t base_path_length, int read_fd, int write_fd, bool recursive) 58 Node(FSEventsWatcher* watcher, intptr_t base_path_length, int read_fd,
59 : base_path_length_(base_path_length), 59 int write_fd, bool recursive)
60 read_fd_(read_fd), 60 : watcher_(watcher),
61 write_fd_(write_fd), 61 ready_(false),
Søren Gjesse 2014/02/06 13:04:19 Indent
Anders Johnsen 2014/02/06 13:15:22 Done.
62 recursive_(recursive), 62 base_path_length_(base_path_length),
63 ref_(NULL) {} 63 read_fd_(read_fd),
64 write_fd_(write_fd),
65 recursive_(recursive),
66 ref_(NULL) {}
64 67
65 ~Node() { 68 ~Node() {
66 close(write_fd_); 69 close(write_fd_);
67 FSEventStreamInvalidate(ref_);
68 FSEventStreamRelease(ref_);
69 } 70 }
70 71
71 void set_ref(FSEventStreamRef ref) { 72 void set_ref(FSEventStreamRef ref) {
72 ref_ = ref; 73 ref_ = ref;
73 } 74 }
74 75
76 static void StartCallback(CFRunLoopTimerRef timer, void* info) {
77 Node* node = reinterpret_cast<Node*>(info);
78 FSEventStreamScheduleWithRunLoop(
79 node->ref_,
80 node->watcher_->run_loop_,
81 kCFRunLoopDefaultMode);
82 FSEventStreamStart(node->ref_);
83 FSEventStreamFlushSync(node->ref_);
84 node->watcher_->monitor_.Enter();
85 node->ready_ = true;
86 node->watcher_->monitor_.Notify();
87 node->watcher_->monitor_.Exit();
88 }
89
75 void Start() { 90 void Start() {
Søren Gjesse 2014/02/06 13:04:19 ASSERT(!ready_)
Anders Johnsen 2014/02/06 13:15:22 Done.
76 FSEventStreamStart(ref_); 91 CFRunLoopTimerContext context;
92 memset(&context, 0, sizeof(context));
93 context.info = this;
94 CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
95 NULL, 0, 0, 0, 0, StartCallback, &context);
96 CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
97 watcher_->monitor_.Enter();
98 while (!ready_) {
99 watcher_->monitor_.Wait(Monitor::kNoTimeout);
100 }
101 watcher_->monitor_.Exit();
102 }
103
104 static void StopCallback(CFRunLoopTimerRef timer, void* info) {
105 Node* node = reinterpret_cast<Node*>(info);
106 FSEventStreamStop(node->ref_);
107 FSEventStreamInvalidate(node->ref_);
108 FSEventStreamRelease(node->ref_);
109 node->watcher_->monitor_.Enter();
110 node->ready_ = false;
111 node->watcher_->monitor_.Notify();
112 node->watcher_->monitor_.Exit();
77 } 113 }
78 114
79 void Stop() { 115 void Stop() {
Søren Gjesse 2014/02/06 13:04:19 ASSERT(ready_)
Anders Johnsen 2014/02/06 13:15:22 Done.
80 FSEventStreamStop(ref_); 116 CFRunLoopTimerContext context;
117 memset(&context, 0, sizeof(context));
118 context.info = this;
119 CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
120 NULL, 0, 0, 0, 0, StopCallback, &context);
121 CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
122 watcher_->monitor_.Enter();
123 while (ready_) {
124 watcher_->monitor_.Wait(Monitor::kNoTimeout);
125 }
126 watcher_->monitor_.Exit();
81 } 127 }
82 128
129 bool ready() const { return ready_; }
83 intptr_t base_path_length() const { return base_path_length_; } 130 intptr_t base_path_length() const { return base_path_length_; }
84 int read_fd() const { return read_fd_; } 131 int read_fd() const { return read_fd_; }
85 int write_fd() const { return write_fd_; } 132 int write_fd() const { return write_fd_; }
86 bool recursive() const { return recursive_; } 133 bool recursive() const { return recursive_; }
87 134
88 private: 135 private:
136 FSEventsWatcher* watcher_;
137 bool ready_;
89 intptr_t base_path_length_; 138 intptr_t base_path_length_;
90 int read_fd_; 139 int read_fd_;
91 int write_fd_; 140 int write_fd_;
92 bool recursive_; 141 bool recursive_;
93 FSEventStreamRef ref_; 142 FSEventStreamRef ref_;
94 }; 143 };
95 144
96 FSEventsWatcher() : run_loop_(0) { 145 FSEventsWatcher() : run_loop_(0) {
97 Thread::Start(Run, reinterpret_cast<uword>(this)); 146 Thread::Start(Run, reinterpret_cast<uword>(this));
98 } 147 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 int fds[2]; 185 int fds[2];
137 VOID_TEMP_FAILURE_RETRY(pipe(fds)); 186 VOID_TEMP_FAILURE_RETRY(pipe(fds));
138 Socket::SetNonBlocking(fds[0]); 187 Socket::SetNonBlocking(fds[0]);
139 Socket::SetBlocking(fds[1]); 188 Socket::SetBlocking(fds[1]);
140 189
141 char base_path[PATH_MAX]; 190 char base_path[PATH_MAX];
142 realpath(path, base_path); 191 realpath(path, base_path);
143 CFStringRef path_ref = CFStringCreateWithCString( 192 CFStringRef path_ref = CFStringCreateWithCString(
144 NULL, base_path, kCFStringEncodingUTF8); 193 NULL, base_path, kCFStringEncodingUTF8);
145 194
146 Node* node = new Node(strlen(base_path), fds[0], fds[1], recursive); 195 Node* node = new Node(this, strlen(base_path), fds[0], fds[1], recursive);
147 196
148 FSEventStreamContext context; 197 FSEventStreamContext context;
149 context.version = 0; 198 context.version = 0;
150 context.info = reinterpret_cast<void*>(node); 199 context.info = reinterpret_cast<void*>(node);
151 context.retain = NULL; 200 context.retain = NULL;
152 context.release = NULL; 201 context.release = NULL;
153 context.copyDescription = NULL; 202 context.copyDescription = NULL;
154 FSEventStreamRef ref = FSEventStreamCreate( 203 FSEventStreamRef ref = FSEventStreamCreate(
155 NULL, 204 NULL,
156 Callback, 205 Callback,
157 &context, 206 &context,
158 CFArrayCreate(NULL, reinterpret_cast<const void**>(&path_ref), 1, NULL), 207 CFArrayCreate(NULL, reinterpret_cast<const void**>(&path_ref), 1, NULL),
159 kFSEventStreamEventIdSinceNow, 208 kFSEventStreamEventIdSinceNow,
160 0.10, 209 0.10,
161 kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents); 210 kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);
162 211
163 node->set_ref(ref); 212 node->set_ref(ref);
164 213
165 FSEventStreamScheduleWithRunLoop(
166 ref,
167 run_loop_,
168 kCFRunLoopDefaultMode);
169
170 return node; 214 return node;
171 } 215 }
172 216
173 private: 217 private:
174 static void Callback(ConstFSEventStreamRef ref, 218 static void Callback(ConstFSEventStreamRef ref,
175 void* client, 219 void* client,
176 size_t num_events, 220 size_t num_events,
177 void* event_paths, 221 void* event_paths,
178 const FSEventStreamEventFlags event_flags[], 222 const FSEventStreamEventFlags event_flags[],
179 const FSEventStreamEventId event_ids[]) { 223 const FSEventStreamEventId event_ids[]) {
180 Node* node = reinterpret_cast<Node*>(client); 224 Node* node = reinterpret_cast<Node*>(client);
Søren Gjesse 2014/02/06 13:04:19 Need to protect access to ready with the monitor.
Anders Johnsen 2014/02/06 13:15:22 As discussed offline, is on same thread as run-loo
225 if (!node->ready()) return;
181 for (size_t i = 0; i < num_events; i++) { 226 for (size_t i = 0; i < num_events; i++) {
182 char *path = reinterpret_cast<char**>(event_paths)[i]; 227 char *path = reinterpret_cast<char**>(event_paths)[i];
183 FSEvent event; 228 FSEvent event;
184 event.data.exists = File::GetType(path, false) != File::kDoesNotExist; 229 event.data.exists = File::GetType(path, false) != File::kDoesNotExist;
185 path += node->base_path_length(); 230 path += node->base_path_length();
186 // If path is longer the base, skip next character ('/'). 231 // If path is longer the base, skip next character ('/').
187 if (path[0] != '\0') path += 1; 232 if (path[0] != '\0') path += 1;
188 if (!node->recursive() && strstr(path, "/") != NULL) continue; 233 if (!node->recursive() && strstr(path, "/") != NULL) continue;
189 event.data.flags = event_flags[i]; 234 event.data.flags = event_flags[i];
190 memmove(event.data.path, path, strlen(path) + 1); 235 memmove(event.data.path, path, strlen(path) + 1);
191 write(node->write_fd(), event.bytes, sizeof(event)); 236 write(node->write_fd(), event.bytes, sizeof(event));
192 } 237 }
193 } 238 }
194 239
195 Monitor monitor_; 240 Monitor monitor_;
196 CFRunLoopRef run_loop_; 241 CFRunLoopRef run_loop_;
197 }; 242 };
198 243
199 244
200 #define kCFCoreFoundationVersionNumber10_7 635.00 245 #define kCFCoreFoundationVersionNumber10_7 635.00
201 bool FileSystemWatcher::IsSupported() { 246 bool FileSystemWatcher::IsSupported() {
202 return kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_7; 247 return kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_7;
203 } 248 }
204 249
205 250
206 intptr_t FileSystemWatcher::Init() { 251 intptr_t FileSystemWatcher::Init() {
207 FSEventsWatcher* watcher = new FSEventsWatcher(); 252 FSEventsWatcher* watcher = new FSEventsWatcher();
208 watcher->monitor().Enter(); 253 watcher->monitor().Enter();
209 while (!watcher->has_run_loop()) { 254 while (!watcher->has_run_loop()) {
210 watcher->monitor().Wait(1); 255 watcher->monitor().Wait(Monitor::kNoTimeout);
211 } 256 }
212 watcher->monitor().Exit(); 257 watcher->monitor().Exit();
213 return reinterpret_cast<intptr_t>(watcher); 258 return reinterpret_cast<intptr_t>(watcher);
214 } 259 }
215 260
216 261
217 void FileSystemWatcher::Close(intptr_t id) { 262 void FileSystemWatcher::Close(intptr_t id) {
218 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(id); 263 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(id);
219 delete watcher; 264 delete watcher;
220 } 265 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 } 336 }
292 return events; 337 return events;
293 } 338 }
294 339
295 } // namespace bin 340 } // namespace bin
296 } // namespace dart 341 } // namespace dart
297 342
298 #endif // defined(TARGET_OS_MACOS) 343 #endif // defined(TARGET_OS_MACOS)
299 344
300 345
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698