From 66227bea04b2bde5dbe039786519587891d7f1b1 Mon Sep 17 00:00:00 2001 From: WangKe Date: Thu, 17 Apr 2025 11:58:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dwatcher=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98=20openmode=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20stream.write=E5=BC=82=E5=B8=B8=E6=8A=9B=E5=87=BA?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20readtext=E4=BF=AE=E5=A4=8D=20update=20inte?= =?UTF-8?q?rfaces/kits/js/src/common/ani=5Fhelper/type=5Fconverter.cpp.=20?= =?UTF-8?q?update=20interfaces/kits/js/src/common/ani=5Fhelper/type=5Fconv?= =?UTF-8?q?erter.cpp.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WangKe Change-Id: I8596f24a42cd823c78af6d6a56819932b7c73f7a --- .../js/src/common/ani_helper/ani_helper.h | 2 +- .../src/common/ani_helper/type_converter.cpp | 13 ++++ .../js/src/common/ani_helper/type_converter.h | 1 + .../js/src/mod_fs/ani/ets/@ohos.file.fs.ets | 36 ++++++----- .../mod_fs/class_stream/ani/stream_ani.cpp | 7 ++- .../ani/watch_event_listener.cpp | 5 +- .../mod_fs/class_watcher/fs_file_watcher.cpp | 62 ++++++++++++++++--- .../mod_fs/class_watcher/fs_file_watcher.h | 9 ++- .../mod_fs/properties/ani/read_text_ani.cpp | 3 +- 9 files changed, 104 insertions(+), 34 deletions(-) diff --git a/interfaces/kits/js/src/common/ani_helper/ani_helper.h b/interfaces/kits/js/src/common/ani_helper/ani_helper.h index df93167fb..11083ff86 100644 --- a/interfaces/kits/js/src/common/ani_helper/ani_helper.h +++ b/interfaces/kits/js/src/common/ani_helper/ani_helper.h @@ -175,7 +175,7 @@ public: } } - static bool SendEventToMainThread(const function func) + static bool SendEventToMainThread(const function &func) { if (func == nullptr) { HILOGE("func is nullptr!"); diff --git a/interfaces/kits/js/src/common/ani_helper/type_converter.cpp b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp index fe336b31e..bfa635e0e 100644 --- a/interfaces/kits/js/src/common/ani_helper/type_converter.cpp +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.cpp @@ -108,6 +108,19 @@ std::tuple TypeConverter::ToAniString(ani_env *env, std::strin return { true, std::move(result) }; } +std::tuple TypeConverter::ToAniString(ani_env *env, std::string str, size_t size) +{ + if (env == nullptr) { + return { false, {} }; + } + + ani_string result; + if (ANI_OK != env->String_NewUTF8(str.c_str(), size, &result)) { + return { false, {} }; + } + return { true, std::move(result) }; +} + std::tuple TypeConverter::ToAniString(ani_env *env, const char *str) { if (env == nullptr) { diff --git a/interfaces/kits/js/src/common/ani_helper/type_converter.h b/interfaces/kits/js/src/common/ani_helper/type_converter.h index 24bdd736a..a6d062659 100644 --- a/interfaces/kits/js/src/common/ani_helper/type_converter.h +++ b/interfaces/kits/js/src/common/ani_helper/type_converter.h @@ -33,6 +33,7 @@ public: static std::tuple> ToOptionalInt32(ani_env *env, const ani_object &value); static std::tuple> ToOptionalInt64(ani_env *env, const ani_object &value); static std::tuple ToAniString(ani_env *env, std::string str); + static std::tuple ToAniString(ani_env *env, std::string str, size_t size); static std::tuple ToAniString(ani_env *env, const char *str); static std::tuple> EnumToInt32(ani_env *env, const ani_enum_item &enumOp); static std::tuple ToFileInfo(ani_env *env, const ani_object &pathOrFd); diff --git a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets index fa2d2daf8..c43cc008c 100644 --- a/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets +++ b/interfaces/kits/js/src/mod_fs/ani/ets/@ohos.file.fs.ets @@ -15,6 +15,21 @@ import { BusinessError, AsyncCallback } from '@ohos.base'; import stream from '@ohos.util.stream'; +namespace fileIo { + export namespace OpenMode { + export const READ_ONLY = 0o0; + export const WRITE_ONLY = 0o1; + export const READ_WRITE = 0o2; + export const CREATE = 0o100; + export const TRUNC = 0o1000; + export const APPEND = 0o2000; + export const NONBLOCK = 0o4000; + export const DIR = 0o200000; + export const NOFOLLOW = 0o400000; + export const SYNC = 0o4010000; + } +} + function access(path: string, mode?: AccessModeType): Promise { return new Promise((resolve: (result: boolean) => void, reject: (e: BusinessError) => void) => { if (mode === undefined) { @@ -1874,19 +1889,6 @@ class StreamInner implements Stream { native seek(offset: number, whence?: number): number; } -enum OpenMode { - READ_ONLY = 0o0, - WRITE_ONLY = 0o1, - READ_WRITE = 0o2, - CREATE = 0o100, - TRUNC = 0o1000, - APPEND = 0o2000, - NONBLOCK = 0o4000, - DIR = 0o200000, - NOFOLLOW = 0o400000, - SYNC = 0o4010000, -} - export interface ReadStreamOptions { start?: number; end?: number; @@ -2041,16 +2043,16 @@ export class WriteStream extends stream.Writable { if (mode === undefined) { return modeStr; } - if ((mode as number) & OpenMode.WRITE_ONLY) { + if ((mode as number) & fileIo.OpenMode.WRITE_ONLY) { modeStr = 'w'; } - if ((mode as number) & OpenMode.READ_WRITE) { + if ((mode as number) & fileIo.OpenMode.READ_WRITE) { modeStr = 'w+'; } - if (((mode as number) & OpenMode.WRITE_ONLY) && ((mode as number) & OpenMode.APPEND)) { + if (((mode as number) & fileIo.OpenMode.WRITE_ONLY) && ((mode as number) & fileIo.OpenMode.APPEND)) { modeStr = 'a'; } - if (((mode as number) & OpenMode.READ_WRITE) && ((mode as number) & OpenMode.APPEND)) { + if (((mode as number) & fileIo.OpenMode.READ_WRITE) && ((mode as number) & fileIo.OpenMode.APPEND)) { modeStr = 'a+'; } return modeStr; diff --git a/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp index abce84a4d..92cfc402c 100644 --- a/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/class_stream/ani/stream_ani.cpp @@ -190,8 +190,9 @@ ani_double StreamAni::Write(ani_env *env, [[maybe_unused]] ani_object object, an } auto ret = fsStream->Write(buffer, op); if (!ret.IsSuccess()) { - HILOGE("write buffer failed!"); - ErrorHandler::Throw(env, EINVAL); + HILOGE("write string failed!"); + const auto &err = ret.GetError(); + ErrorHandler::Throw(env, err); return -1; } return ret.GetData().value(); @@ -207,9 +208,9 @@ ani_double StreamAni::Write(ani_env *env, [[maybe_unused]] ani_object object, an } auto ret = fsStream->Write(buffer, op); if (!ret.IsSuccess()) { + HILOGE("write buffer failed!"); const auto &err = ret.GetError(); ErrorHandler::Throw(env, err); - HILOGE("write buffer failed!"); return -1; } return static_cast(ret.GetData().value()); diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp index 960dc4352..36ac7517d 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/ani/watch_event_listener.cpp @@ -45,7 +45,6 @@ bool WatchEventListener::IsStrictEquals(const shared_ptr &othe ani_boolean isSame = false; ani_status status = env->Reference_StrictEquals(callback, otherListener->callback, &isSame); - AniHelper::DetachThreadEnv(vm); if (status != ANI_OK) { HILOGE("Compare ref for strict equality failed. status = %{public}d", static_cast(status)); return false; @@ -64,8 +63,8 @@ void WatchEventListener::InvokeCallback(const string &fileName, uint32_t event, watchEvent->fileName = fileName; watchEvent->event = event; watchEvent->cookie = cookie; - SendWatchEvent(*watchEvent); - AniHelper::DetachThreadEnv(vm); + auto task = [this, watchEvent]() { SendWatchEvent(*watchEvent); }; + AniHelper::SendEventToMainThread(task); } inline static const int32_t ANI_SCOPE_SIZE = 16; diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp index f9796486f..24e09e958 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.cpp @@ -28,6 +28,8 @@ namespace OHOS::FileManagement::ModuleFileIO { using namespace std; +mutex FsFileWatcher::watchMutex_; + FsFileWatcher::FsFileWatcher() {} FsFileWatcher::~FsFileWatcher() {} @@ -115,12 +117,10 @@ int32_t FsFileWatcher::NotifyToWatchNewEvents(const string &fileName, const int3 int32_t FsFileWatcher::CloseNotifyFd() { int32_t closeRet = ERRNO_NOERR; - int32_t fd = notifyFd_; if (watcherInfoSet_.size() == 0) { run_ = false; - notifyFd_ = -1; - closeRet = close(fd); + closeRet = close(notifyFd_); if (closeRet != 0) { HILOGE("Failed to stop notify close fd errCode:%{public}d", errno); } @@ -132,9 +132,24 @@ int32_t FsFileWatcher::CloseNotifyFd() eventFd_ = -1; DestroyTaskThead(); } + + closed_ = false; return closeRet; } +int FsFileWatcher::CloseNotifyFdLocked() +{ + { + lock_guard lock(readMutex_); + closed_ = true; + if (reading_) { + HILOGE("close while reading"); + return ERRNO_NOERR; + } + } + return CloseNotifyFd(); +} + int32_t FsFileWatcher::StopNotify(shared_ptr info) { unique_lock lock(watchMutex_); @@ -150,17 +165,26 @@ int32_t FsFileWatcher::StopNotify(shared_ptr info) HILOGE("The Watched file does not exist, and the remaining monitored events will be invalid."); return ERRNO_NOERR; } - if (inotify_rm_watch(notifyFd_, info->wd) == -1) { - int32_t rmErr = errno; + int oldWd = -1; + { + lock_guard lock(readMutex_); + if (!(closed_ && reading_)) { + oldWd = inotify_rm_watch(notifyFd_, info->wd); + } else { + HILOGE("rm watch fail"); + } + } + if (oldWd == -1) { + int rmErr = errno; if (access(info->fileName.c_str(), F_OK) == 0) { HILOGE("Failed to stop notify errCode:%{public}d", rmErr); wdFileNameMap_.erase(info->fileName); - CloseNotifyFd(); + CloseNotifyFdLocked(); return rmErr; } } wdFileNameMap_.erase(info->fileName); - return CloseNotifyFd(); + return CloseNotifyFdLocked(); } void FsFileWatcher::ReadNotifyEvent() @@ -183,6 +207,28 @@ void FsFileWatcher::ReadNotifyEvent() } } +void FsFileWatcher::ReadNotifyEventLocked() +{ + { + lock_guard lock(readMutex_); + if (closed_) { + HILOGE("read after close"); + return; + } + reading_ = true; + } + ReadNotifyEvent(); + { + lock_guard lock(readMutex_); + reading_ = false; + if (closed_) { + HILOGE("close after read"); + CloseNotifyFd(); + return; + } + } +} + void FsFileWatcher::AsyncGetNotifyEvent() { lock_guard lock(taskMutex_); @@ -213,7 +259,7 @@ void FsFileWatcher::GetNotifyEvent() return; } if (static_cast(fds[1].revents) & POLLIN) { - ReadNotifyEvent(); + ReadNotifyEventLocked(); } } else if (ret < 0 && errno == EINTR) { continue; diff --git a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h index 12a8ef7f8..17be3a40a 100644 --- a/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h +++ b/interfaces/kits/js/src/mod_fs/class_watcher/fs_file_watcher.h @@ -50,17 +50,24 @@ private: tuple CheckEventWatched(const string &fileName, const uint32_t &event); void NotifyEvent(const struct inotify_event *event); int CloseNotifyFd(); + int CloseNotifyFdLocked(); int NotifyToWatchNewEvents(const string &fileName, const int &wd, const uint32_t &watchEvents); void ReadNotifyEvent(); + void ReadNotifyEventLocked(); void DestroyTaskThead(); private: + static mutex watchMutex_; + mutex taskMutex_; + mutex readMutex_; + atomic taskRunning_ = false; thread taskThead_; - mutex watchMutex_; bool run_ = false; + bool reading_ = false; + bool closed_ = false; int32_t notifyFd_ = -1; int32_t eventFd_ = -1; unordered_set> watcherInfoSet_; diff --git a/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp b/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp index dc733c606..7e2fe63ff 100644 --- a/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/ani/read_text_ani.cpp @@ -92,7 +92,8 @@ ani_string ReadTextAni::ReadTextSync( const auto &resText = ret.GetData().value(); string res = std::get<0>(resText); - auto [succ, result] = TypeConverter::ToAniString(env, res); + size_t size = std::get<1>(resText); + auto [succ, result] = TypeConverter::ToAniString(env, res, size); if (!succ) { HILOGE("Convert result to ani string failed"); ErrorHandler::Throw(env, UNKNOWN_ERR); -- Gitee