From e27983ccfc9f73e2ec69863dcc5d9812fba7f5ef Mon Sep 17 00:00:00 2001 From: Colm Donelan Date: Mon, 16 Jan 2023 16:45:08 +0000 Subject: IVGCVSW-7405 Improving error handling around creating directories. The -F execute network option creates a directory to print intermediate tensors but minor problems caused serious failures. This attempts to clean up the error handling. Signed-off-by: Colm Donelan Change-Id: Ia44c008919b1bee299b43a672235b1fcc25bf1bd --- src/armnn/Network.cpp | 15 ++++++-- src/armnnUtils/Filesystem.cpp | 41 +++++++++++++++++----- .../test/layerTests/DebugTestImpl.cpp | 7 ++-- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp index 42388bfbd7..e81b87b382 100644 --- a/src/armnn/Network.cpp +++ b/src/armnn/Network.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017,2022,2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -1731,8 +1731,17 @@ IOptimizedNetworkPtr Optimize(const Graph& inGraph, else if (options.m_DebugToFile) { // Setup the output file path - armnnUtils::Filesystem::CreateDirectory("/ArmNNIntermediateLayerOutputs"); - Optimizer::Pass(optGraph, MakeOptimizations(InsertDebugToFileLayer())); + try + { + auto result = armnnUtils::Filesystem::CreateDirectory("/ArmNNIntermediateLayerOutputs"); + ARMNN_LOG(info) << "Intermediate tensors will be written to: " << result; + Optimizer::Pass(optGraph, MakeOptimizations(InsertDebugToFileLayer())); + } + catch (const armnn::RuntimeException& e) + { + // If we cannot create the output directory then we'll issue a warning and continue. + ARMNN_LOG(warning) << "Unable to print intermediate layer outputs : " << e.what(); + } } // Calculate the compatibility strategies for tensor handles diff --git a/src/armnnUtils/Filesystem.cpp b/src/armnnUtils/Filesystem.cpp index 1577d2d07c..78f928a874 100644 --- a/src/armnnUtils/Filesystem.cpp +++ b/src/armnnUtils/Filesystem.cpp @@ -1,11 +1,11 @@ // -// Copyright © 2020 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2020,2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #if !defined(ARMNN_DISABLE_FILESYSTEM) +#include #include -#include "armnn/Exceptions.hpp" namespace armnnUtils { @@ -42,31 +42,54 @@ fs::path NamedTempFile(const char* fileName) * * @param path is the path required in the temporary directory. * @return path consisting of system temporary directory. + * @throws RuntimeException if the directory cannot be created or exists but cannot be removed. */ std::string CreateDirectory(std::string path) { + // This line is very unlikely to throw an exception. fs::path tmpDir = fs::temp_directory_path(); - mode_t permissions = 0733; - int result = 0; - std::string full_path = tmpDir.generic_string() + path; if (fs::exists(full_path)) { - fs::remove_all(full_path); + try + { + // This could throw an exception on a multi-user system. + fs::remove_all(full_path); + } + catch (const std::system_error& e) + { + std::string error = "Directory exists and cannot be removed. Reason: "; + error.append(e.what()); + throw armnn::RuntimeException(error); + } } - #if defined(_WIN32) result = _mkdir(full_path.c_str()); // can be used on Windows armnn::ConditionalThrow((result == 0), "Was unable to create temporary directory"); #else - result = mkdir(full_path.c_str(), permissions); - armnn::ConditionalThrow((result == 0), "Was unable to create temporary directory"); + try + { + if(!fs::create_directory(full_path)) + { + throw armnn::RuntimeException("Unable to create directory: " + full_path); + } + } + catch (const std::system_error& e) + { + std::string error = "Unable to create directory. Reason: "; + error.append(e.what()); + throw armnn::RuntimeException(error); + } #endif return full_path + "/"; } FileContents ReadFileContentsIntoString(const std::string path) { + if (!fs::exists(path)) + { + throw armnn::RuntimeException("Path does not exist: " + path); + } std::ifstream input_file(path); armnn::ConditionalThrow((input_file.is_open()), "Could not read file contents"); return FileContents((std::istreambuf_iterator(input_file)), std::istreambuf_iterator()); diff --git a/src/backends/backendsCommon/test/layerTests/DebugTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/DebugTestImpl.cpp index e2fa8dbf5a..2ec94bca58 100644 --- a/src/backends/backendsCommon/test/layerTests/DebugTestImpl.cpp +++ b/src/backends/backendsCommon/test/layerTests/DebugTestImpl.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2017,2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -72,9 +72,8 @@ LayerTestResult DebugTestImpl( { // Given that this is dependent on an ExNet switch, we need to explicitly set the directory that the // files are stored in as this happens within the ExNet flow - fs::path tmpDir = fs::temp_directory_path(); - armnnUtils::Filesystem::CreateDirectory("/ArmNNIntermediateLayerOutputs"); - std::string full_path = tmpDir.generic_string() + "/ArmNNIntermediateLayerOutputs/" + layerName + ".numpy"; + auto tmpDir = armnnUtils::Filesystem::CreateDirectory("/ArmNNIntermediateLayerOutputs"); + std::string full_path = tmpDir + layerName + ".numpy"; ExecuteWorkload(*workload, memoryManager); -- cgit v1.2.1