| 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 |