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 df93167fb9af830daff087f8a2a9effaaf151cef..11083ff86ac94f879ef36b9e50d3234c5beda0fd 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 fe336b31eabe7bd350027f93ca8431ae651e31ee..bfa635e0e40742fc0906f8935608de95e5cb2c81 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 24bdd736a736c1c26e1deadc3d1dc351573e2817..a6d06265992b98d16aedb01d1a7acf99367e817d 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 fa2d2daf8679d4e5b23aebc0a526b5c155805d80..c43cc008cb540a14348e36bb9cd2c3af60062c32 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 abce84a4d07513b72e48dd90e3495560b081af26..92cfc402cca1232fbdaaa8a9d4aa88cdd79c79b0 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 960dc4352ffc80138f172d2b1a0d4a577b38939d..36ac7517d6d286f627a4ffd4e5c05002e49928d0 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 f9796486f31f5110285e865452ad7ce09e93c22f..24e09e958d69f8ec7383e2a6ffe350e53a79b5d0 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 12a8ef7f88a8388ca9872e903306430b9483a748..17be3a40a699c0077df52cc16e08aa927bb44145 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 dc733c606ba1779568b5d76350ab0c3f8753bfa7..7e2fe63ffbc7b70ec7f3a8440f09e9b28a1d32fe 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);