From 3b97e9d9486ee4e060561ff4e865fe69d448b59f Mon Sep 17 00:00:00 2001 From: fengjq Date: Tue, 24 Oct 2023 22:45:10 +0800 Subject: [PATCH] Bugfix for watcher Signed-off-by: fengjq --- .../mod_fs/class_watcher/watcher_entity.cpp | 65 +++++++++++++++---- .../src/mod_fs/class_watcher/watcher_entity.h | 4 +- .../class_watcher/watcher_n_exporter.cpp | 4 +- 3 files changed, 58 insertions(+), 15 deletions(-) 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 5e9340b79..f44f4560b 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 @@ -27,10 +27,16 @@ using namespace OHOS::FileManagement::LibN; using namespace std; mutex FileWatcher::watchMutex_; +timed_mutex FileWatcher::tmux_; +// mutex FileWatcher::selectMutex_; -FileWatcher::FileWatcher() {} +FileWatcher::FileWatcher() { + HILOGE("FileWatcher::Constructor success"); +} -FileWatcher::~FileWatcher() {} +FileWatcher::~FileWatcher() { + HILOGE("FileWatcher::Destructor success"); +} int32_t FileWatcher::GetNotifyId() { @@ -39,11 +45,14 @@ int32_t FileWatcher::GetNotifyId() bool FileWatcher::InitNotify() { + lock_guard lock(watchMutex_); notifyFd_ = inotify_init(); if (notifyFd_ < 0) { HILOGE("Failed to init notify errCode:%{public}d", errno); return false; } + + HILOGE("FileWatcher::InitNotify has been created, notifyFd_ = %{public}d,", notifyFd_); return true; } @@ -70,7 +79,7 @@ int FileWatcher::StartNotify(shared_ptr arg) } auto [isWatched, wd] = CheckEventWatched(arg->fileName, arg->events); - if (isWatched && wd > 0) { + if (isWatched && wd >= 0) { arg->wd = wd; return ERRNO_NOERR; } @@ -82,12 +91,14 @@ int FileWatcher::StartNotify(shared_ptr arg) } int newWd = inotify_add_watch(notifyFd_, arg->fileName.c_str(), watchEvents); if (newWd < 0) { + int retErr = errno; HILOGE("Failed to start notify errCode:%{public}d", errno); - return errno; + return retErr; } arg->wd = newWd; wdFileNameMap_[arg->fileName].first = newWd; wdFileNameMap_[arg->fileName].second = watchEvents; + HILOGE("StartNotify wdFileNameMap_ newWd:%{public}d, watchEvents:%{public}d", newWd, watchEvents); return ERRNO_NOERR; } @@ -104,11 +115,13 @@ int FileWatcher::NotifyToWatchNewEvents(const string &fileName, const int &wd, c return EIO; } wdFileNameMap_[fileName].second = watchEvents; + HILOGE("NotifyToWatchNewEvents wdFileNameMap_ fileName:%{public}s, watchEvents:%{public}d", fileName.c_str(), watchEvents); return ERRNO_NOERR; } int FileWatcher::CloseNotifyFd() { + HILOGE("StopNotify watcherInfoSet_ size = %{public}u", watcherInfoSet_.size()); int closeRet = ERRNO_NOERR; if (watcherInfoSet_.size() == 0) { closeRet = close(notifyFd_); @@ -133,6 +146,7 @@ int FileWatcher::StopNotify(shared_ptr arg) if (newEvents > 0) { return NotifyToWatchNewEvents(arg->fileName, arg->wd, newEvents); } + HILOGE("StopNotify-Is no event ? :%{public}d", newEvents); if (inotify_rm_watch(notifyFd_, arg->wd) == -1) { int rmErr = errno; if (access(arg->fileName.c_str(), F_OK) == 0) { @@ -142,36 +156,58 @@ int FileWatcher::StopNotify(shared_ptr arg) return rmErr; } } + wdFileNameMap_.erase(arg->fileName); return CloseNotifyFd(); } -void FileWatcher::GetNotifyEvent(WatcherCallback callback) +int FileWatcher::GetNotifyEvent(WatcherCallback callback) { - if (run_) { - return; + // if (run_) { + // HILOGE("GetNotifyEvent wdFileNameMap_ is not empty %{public}u", wdFileNameMap_.size()); + // return ERRNO_NOERR; + // } + if (!tmux_.try_lock_for(chrono::milliseconds(WAIT_MS_TIME))) { + HILOGE("GetNotifyEvent try_lock_for wdFileNameMap_ is not empty %{public}u", wdFileNameMap_.size()); + return ERRNO_NOERR; } + // unique_lock lock(selectMutex_, std::try_to_lock); + // if (!lock.try_lock()) { + // return ERRNO_NOERR; + // } run_ = true; char buf[BUF_SIZE] = {0}; struct inotify_event *event = nullptr; fd_set fds; FD_ZERO(&fds); FD_SET(notifyFd_, &fds); + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 1000; while (run_) { if (notifyFd_ < 0) { - HILOGE("Failed to run Listener Thread because notifyFd_:%{public}d", notifyFd_); + HILOGE("Failed to run Listener Thread because notifyFd_:%{public}d, is map empty: %{public}d", notifyFd_, wdFileNameMap_.empty()); break; } - if (select(notifyFd_ + 1, &fds, nullptr, nullptr, nullptr) > 0) { + HILOGE("GetNotifyEvent-select before"); + int ret = select(notifyFd_ + 1, &fds, nullptr, nullptr, &tv); + if (ret > 0) { + HILOGE("GetNotifyEvent-select ret :%{public}d, fd = %{public}d", ret, notifyFd_); int len, index = 0; while (((len = read(notifyFd_, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; while (index < len) { + HILOGE("GetNotifyEvent-select success, events have been chufa ", errno); event = reinterpret_cast(buf + index); NotifyEvent(event, callback); index += sizeof(struct inotify_event) + event->len; } } + HILOGE("GetNotifyEvent-read after"); } + + tmux_.unlock(); + HILOGE("GetNotifyEvent-while end, wdFileNameMap size:%{public}u", wdFileNameMap_.size()); + return ERRNO_NOERR; } bool FileWatcher::AddWatcherInfo(const string &fileName, shared_ptr arg) @@ -195,10 +231,11 @@ uint32_t FileWatcher::RemoveWatcherInfo(shared_ptr arg) watcherInfoSet_.erase(arg); uint32_t otherEvents = 0; for (const auto &iter : watcherInfoSet_) { - if (iter->fileName == arg->fileName && iter->wd > 0) { + if (iter->fileName == arg->fileName && iter->wd >= 0) { otherEvents |= iter->events; } } + HILOGE("After RemoveWatcherInfo watcherInfoSet_ size:%{public}u", watcherInfoSet_.size()); return otherEvents; } @@ -212,7 +249,7 @@ bool CheckIncludeEvent(const uint32_t &mask, const uint32_t &event) void FileWatcher::NotifyEvent(const struct inotify_event *event, WatcherCallback callback) { - lock_guard lock(watchMutex_); + // lock_guard lock(watchMutex_); string tempFileName; auto found = find_if(wdFileNameMap_.begin(), wdFileNameMap_.end(), [event](const pair> &iter) { @@ -221,19 +258,23 @@ void FileWatcher::NotifyEvent(const struct inotify_event *event, WatcherCallback if (found != wdFileNameMap_.end()) { tempFileName = found->first; } + HILOGE("NotifyEvent tempFileName:%{public}s", tempFileName.c_str()); for (const auto &iter : watcherInfoSet_) { string fileName = tempFileName; uint32_t watchEvent = 0; - if ((iter->fileName == fileName) && (iter->wd > 0)) { + if ((iter->fileName == fileName) && (iter->wd >= 0)) { + HILOGE("NotifyEvent iter->fileName:%{public}s, iter->wd:%{public}d", iter->fileName.c_str(), iter->wd); watchEvent = iter->events; } if (!CheckIncludeEvent(event->mask, watchEvent)) { + HILOGE("NotifyEvent CheckIncludeEvent invalid event mask:%{public}d, watchEvent:%{public}d", event->mask, watchEvent); continue; } if (event->len > 0) { fileName += "/" + string(event->name); } + HILOGE("NotifyEvent callback event mask:%{public}d", event->mask); callback(iter->env, iter->nRef, fileName, event->mask & IN_ALL_EVENTS, event->cookie); } } 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 37db1b7bf..31191ed81 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 @@ -33,6 +33,7 @@ using WatcherCallback = void (*)(napi_env env, const uint32_t &cookie); constexpr int BUF_SIZE = 1024; +constexpr int WAIT_MS_TIME = 10; struct WatcherInfoArg { std::string fileName = ""; uint32_t events = 0; @@ -55,7 +56,7 @@ public: bool InitNotify(); int StartNotify(std::shared_ptr arg); int StopNotify(std::shared_ptr arg); - void GetNotifyEvent(WatcherCallback callback); + int GetNotifyEvent(WatcherCallback callback); bool AddWatcherInfo(const std::string &fileName, std::shared_ptr arg); bool CheckEventValid(const uint32_t &event); private: @@ -67,6 +68,7 @@ private: private: static std::mutex watchMutex_; + static std::timed_mutex tmux_; bool run_ = false; int32_t notifyFd_ = -1; std::unordered_set> watcherInfoSet_; diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_n_exporter.cpp index 30f49cf5f..cd5181040 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/watcher_n_exporter.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/watcher_n_exporter.cpp @@ -101,8 +101,8 @@ napi_value WatcherNExporter::Start(napi_env env, napi_callback_info info) } auto cbExec = []() -> NError { - FileWatcher::GetInstance().GetNotifyEvent(WatcherCallback); - return NError(ERRNO_NOERR); + int ret = FileWatcher::GetInstance().GetNotifyEvent(WatcherCallback); + return NError(ret); }; auto cbCompl = [](napi_env env, NError err) -> NVal { -- Gitee