diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp index 5e9340b791e4817d610a9564fd453a22539c795a..259c4098bc5d74c0dd711de90ac7d12935eecb93 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.cpp @@ -14,10 +14,12 @@ */ #include "watcher_entity.h" +#include #include #include +#include +#include #include -#include #include "filemgmt_libhilog.h" #include "uv.h" @@ -44,6 +46,11 @@ bool FileWatcher::InitNotify() HILOGE("Failed to init notify errCode:%{public}d", errno); return false; } + eventFd_ = eventfd(0, EFD_CLOEXEC); + if (eventFd_ < 0) { + HILOGE("Failed to init eventfd errCode:%{public}d", errno); + return false; + } return true; } @@ -116,6 +123,11 @@ int FileWatcher::CloseNotifyFd() HILOGE("Failed to stop notify close fd errCode:%{public}d", closeRet); } notifyFd_ = -1; + closeRet = close(eventFd_); + if (closeRet != 0) { + HILOGE("Failed to close eventfd errCode:%{public}d", closeRet); + } + eventFd_ = -1; run_ = false; } @@ -131,7 +143,11 @@ int FileWatcher::StopNotify(shared_ptr arg) } uint32_t newEvents = RemoveWatcherInfo(arg); if (newEvents > 0) { - return NotifyToWatchNewEvents(arg->fileName, arg->wd, newEvents); + if (access(arg->fileName.c_str(), F_OK) == 0) { + return NotifyToWatchNewEvents(arg->fileName, arg->wd, newEvents); + } + HILOGE("The Watched file does not exist, and the remaining monitored events will be invalid."); + return ERRNO_NOERR; } if (inotify_rm_watch(notifyFd_, arg->wd) == -1) { int rmErr = errno; @@ -146,30 +162,48 @@ int FileWatcher::StopNotify(shared_ptr arg) return CloseNotifyFd(); } +void FileWatcher::ReadNotifyEvent(WatcherCallback callback) +{ + int len = 0; + int index = 0; + char buf[BUF_SIZE] = {0}; + struct inotify_event *event = nullptr; + while (((len = read(notifyFd_, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; + while (index < len) { + event = reinterpret_cast(buf + index); + NotifyEvent(event, callback); + index += sizeof(struct inotify_event) + event->len; + } +} + void FileWatcher::GetNotifyEvent(WatcherCallback callback) { if (run_) { return; } run_ = true; - char buf[BUF_SIZE] = {0}; - struct inotify_event *event = nullptr; - fd_set fds; - FD_ZERO(&fds); - FD_SET(notifyFd_, &fds); + nfds_t nfds = 2; + struct pollfd fds[2]; + fds[0].fd = eventFd_; + fds[0].events = 0; + fds[1].fd = notifyFd_; + fds[1].events = POLLIN; + int ret = 0; while (run_) { - if (notifyFd_ < 0) { - HILOGE("Failed to run Listener Thread because notifyFd_:%{public}d", notifyFd_); - break; - } - if (select(notifyFd_ + 1, &fds, nullptr, nullptr, nullptr) > 0) { - int len, index = 0; - while (((len = read(notifyFd_, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; - while (index < len) { - event = reinterpret_cast(buf + index); - NotifyEvent(event, callback); - index += sizeof(struct inotify_event) + event->len; + ret = poll(fds, nfds, -1); + if (ret > 0) { + if (fds[0].revents & POLLNVAL) { + run_ = false; + return; } + if (fds[1].revents & POLLIN) { + ReadNotifyEvent(callback); + } + } else if (ret < 0 && errno == EINTR) { + continue; + } else { + HILOGE("Failed to poll NotifyFd, errno=%{public}d", errno); + return; } } } diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.h b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.h index 37db1b7bf9227d950edbe9ae09202a5ad619a534..f486a7bbe2e1b4f0c7218970f3a401055317a8f7 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.h +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_entity.h @@ -56,6 +56,7 @@ public: int StartNotify(std::shared_ptr arg); int StopNotify(std::shared_ptr arg); void GetNotifyEvent(WatcherCallback callback); + void ReadNotifyEvent(WatcherCallback callback); bool AddWatcherInfo(const std::string &fileName, std::shared_ptr arg); bool CheckEventValid(const uint32_t &event); private: @@ -69,6 +70,7 @@ private: static std::mutex watchMutex_; bool run_ = false; int32_t notifyFd_ = -1; + int32_t eventFd_ = -1; std::unordered_set> watcherInfoSet_; std::unordered_map> wdFileNameMap_; };