From edb2ba303425d2964c48700570c12da1fb3a4217 Mon Sep 17 00:00:00 2001 From: Wang Luyao Date: Thu, 15 Aug 2024 02:29:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAstream=E6=B5=81=E5=8A=A0=E9=94=81?= =?UTF-8?q?=E9=98=B2=E6=AD=A2crash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Wang Luyao --- interfaces/kits/js/BUILD.gn | 1 + .../kits/js/src/mod_fs/class_stream/flush.cpp | 15 +++- .../src/mod_fs/class_stream/stream_entity.cpp | 43 ++++++++++ .../src/mod_fs/class_stream/stream_entity.h | 8 ++ .../mod_fs/class_stream/stream_n_exporter.cpp | 81 ++++++++++++++----- .../mod_fs/class_stream/stream_n_exporter.h | 2 + 6 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 interfaces/kits/js/src/mod_fs/class_stream/stream_entity.cpp diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index c98a406bb..2a2a83121 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -216,6 +216,7 @@ ohos_shared_library("fs") { "src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp", "src/mod_fs/class_stream/flush.cpp", "src/mod_fs/class_stream/stream_n_exporter.cpp", + "src/mod_fs/class_stream/stream_entity.cpp", "src/mod_fs/class_tasksignal/task_signal_entity.cpp", "src/mod_fs/class_tasksignal/task_signal_n_exporter.cpp", "src/mod_fs/class_watcher/watcher_entity.cpp", diff --git a/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp b/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp index 105eab7ba..35f7a033b 100755 --- a/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp +++ b/interfaces/kits/js/src/mod_fs/class_stream/flush.cpp @@ -20,6 +20,7 @@ #include "class_stat/stat_entity.h" #include "class_stat/stat_n_exporter.h" #include "filemgmt_libhilog.h" +#include "n_error.h" #include "stream_entity.h" namespace OHOS { @@ -28,6 +29,16 @@ namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; +static int32_t FlushCore(StreamEntity *streamEntity) +{ + int32_t ret = 0; + if (streamEntity->ExecuteStart()) { + ret = fflush(streamEntity->fp.get()); + streamEntity->ExecuteEnd(); + } + return ret; +} + napi_value Flush::Sync(napi_env env, napi_callback_info info) { NFuncArg funcArg(env, info); @@ -43,8 +54,8 @@ napi_value Flush::Sync(napi_env env, napi_callback_info info) NError(EIO).ThrowErr(env); return nullptr; } + int32_t ret = FlushCore(streamEntity); - int ret = fflush(streamEntity->fp.get()); if (ret < 0) { HILOGE("Failed to fflush file in the stream, ret: %{public}d", ret); NError(errno).ThrowErr(env); @@ -74,7 +85,7 @@ napi_value Flush::Async(napi_env env, napi_callback_info info) HILOGE("Stream has been closed in flush cbExec possibly"); return NError(EIO); } - int ret = fflush(streamEntity->fp.get()); + int32_t ret = FlushCore(streamEntity); if (ret < 0) { HILOGE("Failed to fflush file in the stream"); return NError(errno); diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.cpp b/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.cpp new file mode 100644 index 000000000..ed8fb2764 --- /dev/null +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.cpp @@ -0,0 +1,43 @@ +#include "stream_entity.h" +#include "filemgmt_libhilog.h" +#include + +namespace OHOS { +namespace FileManagement { +namespace ModuleFileIO { + StreamEntity::~StreamEntity() { + HILOGE("~StreamEntity"); + std::unique_lock lock(mutex); + if (count > 0) { + HILOGE("count is %{public}d", count); + cv.wait_for(lock, std::chrono::seconds(30), [&]() { + HILOGE("count is %{public}d", count); + return count == 0; + }); + } else { + HILOGE("count is 0"); + } + } + bool StreamEntity::ExecuteStart() { + std::lock_guard lock(mutex); + if (isClose) { + return false; + } + count++; + HILOGE("count is %{public}d", count); + return true; + } + + void StreamEntity::ExecuteEnd() { + std::lock_guard lock(mutex); + count--; + HILOGE("count is %{public}d", count); + if (count == 0 && isClose) { + fp.reset(); + HILOGE("count is 0, do notify"); + cv.notify_all(); + } + } +} +} +} \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h b/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h index 11cdae1dc..60ed185ae 100755 --- a/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_entity.h @@ -16,11 +16,19 @@ #ifndef INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_STREAM_STREAM_ENTITY_H #define INTERFACES_KITS_JS_SRC_MOD_FILEIO_CLASS_STREAM_STREAM_ENTITY_H +#include namespace OHOS { namespace FileManagement { namespace ModuleFileIO { struct StreamEntity { + uint32_t count = 0; + bool isClose = false; + std::mutex mutex; + std::condition_variable cv; std::unique_ptr fp = { nullptr, fclose }; + ~StreamEntity(); + bool ExecuteStart(); + void ExecuteEnd(); }; } // namespace ModuleFileIO diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp index d220521a9..062b8a738 100644 --- a/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.cpp @@ -37,6 +37,42 @@ namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; +static int32_t FseekCore(StreamEntity *streamEntity, long offset) { + int ret = 0; + if (streamEntity->ExecuteStart()) { + ret = fseek(streamEntity->fp.get(), offset, SEEK_SET); + streamEntity->ExecuteEnd(); + } + return ret; +} + +static size_t WriteCore(StreamEntity *streamEntity, void * buf, int32_t len) { + size_t writeLen = 0; + if (streamEntity->ExecuteStart()) { + writeLen = fwrite(buf, 1, len, streamEntity->fp.get()); + streamEntity->ExecuteEnd(); + } + return writeLen; +} + +static size_t ReadCore(StreamEntity *streamEntity, void * buf, int32_t len) { + size_t readLen = 0; + if (streamEntity->ExecuteStart()) { + readLen = fread(buf, 1, len, streamEntity->fp.get()); + streamEntity->ExecuteEnd(); + } + return readLen; +} + +static int32_t FtellCore(StreamEntity *streamEntity) +{ + int32_t ret = 0; + if (streamEntity->ExecuteStart()) { + ret = ftell(streamEntity->fp.get()); + streamEntity->ExecuteEnd(); + } + return ret; +} napi_value StreamNExporter::ReadSync(napi_env env, napi_callback_info cbInfo) { NFuncArg funcArg(env, cbInfo); @@ -63,7 +99,7 @@ napi_value StreamNExporter::ReadSync(napi_env env, napi_callback_info cbInfo) } if (offset >= 0) { - int ret = fseek(filp, static_cast(offset), SEEK_SET); + int32_t ret = FseekCore(streamEntity, offset); if (ret < 0) { HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); NError(errno).ThrowErr(env); @@ -71,7 +107,7 @@ napi_value StreamNExporter::ReadSync(napi_env env, napi_callback_info cbInfo) } } - size_t actLen = fread(buf, 1, len, filp); + size_t actLen = ReadCore(streamEntity, buf, len); if ((actLen != static_cast(len) && !feof(filp)) || ferror(filp)) { HILOGE("Invalid buffer size and pointer, actlen: %{public}zu", actLen); NError(EIO).ThrowErr(env); @@ -96,9 +132,13 @@ napi_value StreamNExporter::CloseSync(napi_env env, napi_callback_info cbInfo) NError(EIO).ThrowErr(env); return nullptr; } - streamEntity->fp.reset(); - (void)NClass::RemoveEntityOfFinal(env, funcArg.GetThisVar()); - + { + std::lock_guard lock(streamEntity->mutex); + streamEntity->isClose = true; + if (streamEntity->count == 0) { + streamEntity->fp.reset(); + } + } return NVal::CreateUndefined(env).val_; } @@ -126,8 +166,9 @@ napi_value StreamNExporter::WriteSync(napi_env env, napi_callback_info cbInfo) HILOGE("Failed to resolve buf and options"); return nullptr; } + if (offset >= 0) { - int ret = fseek(filp, static_cast(offset), SEEK_SET); + int32_t ret = FseekCore(streamEntity, offset); if (ret < 0) { HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); NError(errno).ThrowErr(env); @@ -135,7 +176,7 @@ napi_value StreamNExporter::WriteSync(napi_env env, napi_callback_info cbInfo) } } - size_t writeLen = fwrite(buf, 1, len, filp); + size_t writeLen = WriteCore(streamEntity, buf, len); if ((writeLen == 0) && (writeLen != len)) { HILOGE("Failed to fwrite stream"); NError(EIO).ThrowErr(env); @@ -166,13 +207,13 @@ static napi_value WriteExec(napi_env env, NFuncArg &funcArg, StreamEntity *strea return NError(EIO); } if (offset >= 0) { - int ret = fseek(streamEntity->fp.get(), static_cast(offset), SEEK_SET); + int ret = FseekCore(streamEntity, offset); if (ret < 0) { HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); return NError(errno); } } - arg->actLen = fwrite(buf, 1, len, streamEntity->fp.get()); + arg->actLen = WriteCore(streamEntity, buf, len); if ((arg->actLen == 0) && (arg->actLen != len)) { HILOGE("Failed to fwrite stream"); return NError(EIO); @@ -238,12 +279,12 @@ static napi_value ReadExec(napi_env env, NFuncArg &funcArg, StreamEntity *stream return NError(EIO); } if (offset >= 0) { - if (fseek(streamEntity->fp.get(), static_cast(offset), SEEK_SET) < 0) { + if (FseekCore(streamEntity, offset) < 0) { HILOGE("Failed to set the offset location of the file stream pointer"); return NError(errno); } } - size_t actLen = fread(buf, 1, len, streamEntity->fp.get()); + size_t actLen = ReadCore(streamEntity, buf, len); if ((actLen != static_cast(len) && !feof(streamEntity->fp.get())) || ferror(streamEntity->fp.get())) { HILOGE("Invalid buffer size and pointer, actlen: %{public}zu", actLen); return NError(EIO); @@ -304,14 +345,12 @@ napi_value StreamNExporter::Close(napi_env env, napi_callback_info cbInfo) NError(EIO).ThrowErr(env); return nullptr; } - - auto fp = NClass::RemoveEntityOfFinal(env, funcArg.GetThisVar()); - if (!fp) { - NError(EINVAL).ThrowErr(env); - return nullptr; - } - - auto cbExec = []() -> NError { + auto cbExec = [streamEntity]() -> NError { + std::lock_guard lock(streamEntity->mutex); + streamEntity->isClose = true; + if (streamEntity->count == 0) { + streamEntity->fp.reset(); + } return NError(ERRNO_NOERR); }; @@ -367,14 +406,14 @@ napi_value StreamNExporter::Seek(napi_env env, napi_callback_info cbInfo) } if (offset >= 0) { - int ret = fseek(streamEntity->fp.get(), static_cast(offset), whence); + int ret = FseekCore(streamEntity, offset); if (ret < 0) { HILOGE("Failed to set the offset location of the file stream pointer, ret: %{public}d", ret); NError(errno).ThrowErr(env); return nullptr; } } - int64_t res = ftell(streamEntity->fp.get()); + int64_t res = FtellCore(streamEntity); if (res < 0) { HILOGE("Failed to tell, error:%{public}d", errno); NError(errno).ThrowErr(env); diff --git a/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h index fb7f0fb3b..5dcf62e13 100644 --- a/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h +++ b/interfaces/kits/js/src/mod_fs/class_stream/stream_n_exporter.h @@ -44,6 +44,8 @@ public: ~StreamNExporter() override; }; + + struct AsyncReadArg { size_t lenRead = 0; NRef refReadBuf; -- Gitee