OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/files/file_path_watcher.h" | 5 #include "base/files/file_path_watcher.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <string.h> | 8 #include <string.h> |
9 #include <sys/inotify.h> | 9 #include <sys/inotify.h> |
10 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 FilePath target_; | 145 FilePath target_; |
146 | 146 |
147 // The vector of watches and next component names for all path components, | 147 // The vector of watches and next component names for all path components, |
148 // starting at the root directory. The last entry corresponds to the watch for | 148 // starting at the root directory. The last entry corresponds to the watch for |
149 // |target_| and always stores an empty next component name in |subdir_|. | 149 // |target_| and always stores an empty next component name in |subdir_|. |
150 WatchVector watches_; | 150 WatchVector watches_; |
151 | 151 |
152 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); | 152 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); |
153 }; | 153 }; |
154 | 154 |
155 class InotifyReaderTask : public Task { | 155 void InotifyReaderCallback(InotifyReader* reader, int inotify_fd, |
156 public: | 156 int shutdown_fd) { |
157 InotifyReaderTask(InotifyReader* reader, int inotify_fd, int shutdown_fd) | 157 // Make sure the file descriptors are good for use with select(). |
158 : reader_(reader), | 158 CHECK_LE(0, inotify_fd); |
159 inotify_fd_(inotify_fd), | 159 CHECK_GT(FD_SETSIZE, inotify_fd); |
160 shutdown_fd_(shutdown_fd) { | 160 CHECK_LE(0, shutdown_fd); |
161 // Make sure the file descriptors are good for use with select(). | 161 CHECK_GT(FD_SETSIZE, shutdown_fd); |
162 CHECK_LE(0, inotify_fd_); | |
163 CHECK_GT(FD_SETSIZE, inotify_fd_); | |
164 CHECK_LE(0, shutdown_fd_); | |
165 CHECK_GT(FD_SETSIZE, shutdown_fd_); | |
166 } | |
167 | 162 |
168 virtual void Run() { | 163 while (true) { |
169 while (true) { | 164 fd_set rfds; |
170 fd_set rfds; | 165 FD_ZERO(&rfds); |
171 FD_ZERO(&rfds); | 166 FD_SET(inotify_fd, &rfds); |
172 FD_SET(inotify_fd_, &rfds); | 167 FD_SET(shutdown_fd, &rfds); |
173 FD_SET(shutdown_fd_, &rfds); | |
174 | 168 |
175 // Wait until some inotify events are available. | 169 // Wait until some inotify events are available. |
176 int select_result = | 170 int select_result = |
177 HANDLE_EINTR(select(std::max(inotify_fd_, shutdown_fd_) + 1, | 171 HANDLE_EINTR(select(std::max(inotify_fd, shutdown_fd) + 1, |
178 &rfds, NULL, NULL, NULL)); | 172 &rfds, NULL, NULL, NULL)); |
179 if (select_result < 0) { | 173 if (select_result < 0) { |
180 DPLOG(WARNING) << "select failed"; | 174 DPLOG(WARNING) << "select failed"; |
181 return; | 175 return; |
182 } | 176 } |
183 | 177 |
184 if (FD_ISSET(shutdown_fd_, &rfds)) | 178 if (FD_ISSET(shutdown_fd, &rfds)) |
185 return; | 179 return; |
186 | 180 |
187 // Adjust buffer size to current event queue size. | 181 // Adjust buffer size to current event queue size. |
188 int buffer_size; | 182 int buffer_size; |
189 int ioctl_result = HANDLE_EINTR(ioctl(inotify_fd_, FIONREAD, | 183 int ioctl_result = HANDLE_EINTR(ioctl(inotify_fd, FIONREAD, |
190 &buffer_size)); | 184 &buffer_size)); |
191 | 185 |
192 if (ioctl_result != 0) { | 186 if (ioctl_result != 0) { |
193 DPLOG(WARNING) << "ioctl failed"; | 187 DPLOG(WARNING) << "ioctl failed"; |
194 return; | 188 return; |
195 } | 189 } |
196 | 190 |
197 std::vector<char> buffer(buffer_size); | 191 std::vector<char> buffer(buffer_size); |
198 | 192 |
199 ssize_t bytes_read = HANDLE_EINTR(read(inotify_fd_, &buffer[0], | 193 ssize_t bytes_read = HANDLE_EINTR(read(inotify_fd, &buffer[0], |
200 buffer_size)); | 194 buffer_size)); |
201 | 195 |
202 if (bytes_read < 0) { | 196 if (bytes_read < 0) { |
203 DPLOG(WARNING) << "read from inotify fd failed"; | 197 DPLOG(WARNING) << "read from inotify fd failed"; |
204 return; | 198 return; |
205 } | 199 } |
206 | 200 |
207 ssize_t i = 0; | 201 ssize_t i = 0; |
208 while (i < bytes_read) { | 202 while (i < bytes_read) { |
209 inotify_event* event = reinterpret_cast<inotify_event*>(&buffer[i]); | 203 inotify_event* event = reinterpret_cast<inotify_event*>(&buffer[i]); |
210 size_t event_size = sizeof(inotify_event) + event->len; | 204 size_t event_size = sizeof(inotify_event) + event->len; |
211 DCHECK(i + event_size <= static_cast<size_t>(bytes_read)); | 205 DCHECK(i + event_size <= static_cast<size_t>(bytes_read)); |
212 reader_->OnInotifyEvent(event); | 206 reader->OnInotifyEvent(event); |
213 i += event_size; | 207 i += event_size; |
214 } | |
215 } | 208 } |
216 } | 209 } |
217 | 210 } |
218 private: | |
219 InotifyReader* reader_; | |
220 int inotify_fd_; | |
221 int shutdown_fd_; | |
222 | |
223 DISALLOW_COPY_AND_ASSIGN(InotifyReaderTask); | |
224 }; | |
225 | 211 |
226 static base::LazyInstance<InotifyReader> g_inotify_reader = | 212 static base::LazyInstance<InotifyReader> g_inotify_reader = |
227 LAZY_INSTANCE_INITIALIZER; | 213 LAZY_INSTANCE_INITIALIZER; |
228 | 214 |
229 InotifyReader::InotifyReader() | 215 InotifyReader::InotifyReader() |
230 : thread_("inotify_reader"), | 216 : thread_("inotify_reader"), |
231 inotify_fd_(inotify_init()), | 217 inotify_fd_(inotify_init()), |
232 valid_(false) { | 218 valid_(false) { |
233 shutdown_pipe_[0] = -1; | 219 shutdown_pipe_[0] = -1; |
234 shutdown_pipe_[1] = -1; | 220 shutdown_pipe_[1] = -1; |
235 if (inotify_fd_ >= 0 && pipe(shutdown_pipe_) == 0 && thread_.Start()) { | 221 if (inotify_fd_ >= 0 && pipe(shutdown_pipe_) == 0 && thread_.Start()) { |
236 thread_.message_loop()->PostTask( | 222 thread_.message_loop()->PostTask( |
237 FROM_HERE, new InotifyReaderTask(this, inotify_fd_, shutdown_pipe_[0])); | 223 FROM_HERE, base::Bind(&InotifyReaderCallback, this, inotify_fd_, |
| 224 shutdown_pipe_[0])); |
238 valid_ = true; | 225 valid_ = true; |
239 } | 226 } |
240 } | 227 } |
241 | 228 |
242 InotifyReader::~InotifyReader() { | 229 InotifyReader::~InotifyReader() { |
243 if (valid_) { | 230 if (valid_) { |
244 // Write to the self-pipe so that the select call in InotifyReaderTask | 231 // Write to the self-pipe so that the select call in InotifyReaderTask |
245 // returns. | 232 // returns. |
246 ssize_t ret = HANDLE_EINTR(write(shutdown_pipe_[1], "", 1)); | 233 ssize_t ret = HANDLE_EINTR(write(shutdown_pipe_[1], "", 1)); |
247 DPCHECK(ret > 0); | 234 DPCHECK(ret > 0); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 } | 480 } |
494 | 481 |
495 } // namespace | 482 } // namespace |
496 | 483 |
497 FilePathWatcher::FilePathWatcher() { | 484 FilePathWatcher::FilePathWatcher() { |
498 impl_ = new FilePathWatcherImpl(); | 485 impl_ = new FilePathWatcherImpl(); |
499 } | 486 } |
500 | 487 |
501 } // namespace files | 488 } // namespace files |
502 } // namespace base | 489 } // namespace base |
OLD | NEW |