From 358b105b1bca28a856dc6aa4835b0e22e683c85b Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 9 Oct 2017 19:06:26 +0200 Subject: [PATCH] cli: Handle interrupt so setting tags is not force-canceled This should prevent damaged files in case CTRL + C is used to terminate the application during rewrite. --- cli/helper.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ cli/helper.h | 13 +++++++++++++ cli/mainfeatures.cpp | 7 +++++++ 3 files changed, 60 insertions(+) diff --git a/cli/helper.cpp b/cli/helper.cpp index dbcad36..6daab26 100644 --- a/cli/helper.cpp +++ b/cli/helper.cpp @@ -12,6 +12,7 @@ #include #include +#include using namespace std; using namespace std::placeholders; @@ -20,9 +21,48 @@ using namespace ConversionUtilities; using namespace ChronoUtilities; using namespace Media; using namespace Settings; +using namespace EscapeCodes; namespace Cli { +std::function InterruptHandler::s_handler; +bool InterruptHandler::s_handlerRegistered = false; + +InterruptHandler::InterruptHandler(std::function handler) +{ + // set handler function or throw if an instance has already been created + if(s_handler) { + throw runtime_error("Only one instance of InterruptHandler can exist at a time."); + } + s_handler = handler; + + // register handler if not registered yet + if(!s_handlerRegistered) { + s_handlerRegistered = true; + signal(SIGINT, &InterruptHandler::handler); + } +} + +InterruptHandler::~InterruptHandler() +{ + s_handler = function(); +} + +void InterruptHandler::handler(int signum) +{ + // just exit if no custom handler has been defined + if(!s_handler) { + exit(signum); + } + + // print warning + finalizeLog(); + cout << Phrases::Warning << "Interrupt received, trying to abort ongoing process ..." << Phrases::End << flush; + + // call custom handler + s_handler(); +} + string incremented(const string &str, unsigned int toIncrement) { string res; diff --git a/cli/helper.h b/cli/helper.h index 5e45f17..5b0f837 100644 --- a/cli/helper.h +++ b/cli/helper.h @@ -158,6 +158,19 @@ inline FieldValue::FieldValue(DenotationType type, unsigned int fileIndex, const value(value) {} +class InterruptHandler +{ +public: + InterruptHandler(std::function handler); + ~InterruptHandler(); + +private: + static void handler(int signum); + + static std::function s_handler; + static bool s_handlerRegistered; +}; + } // define hash functions for custom data types diff --git a/cli/mainfeatures.cpp b/cli/mainfeatures.cpp index 0ed9a36..4d402de 100644 --- a/cli/mainfeatures.cpp +++ b/cli/mainfeatures.cpp @@ -400,6 +400,9 @@ void setTagInfo(const SetTagInfoArgs &args) fileInfo.setIndexPosition(parsePositionDenotation(args.indexPosArg, args.indexPosValueArg, ElementPosition::BeforeData)); fileInfo.setForceIndexPosition(args.forceIndexPosArg.isPresent()); fileInfo.setForceRewrite(args.forceRewriteArg.isPresent()); + InterruptHandler handler([&fileInfo] { + fileInfo.tryToAbort(); + }); // iterate through all specified files unsigned int fileIndex = 0; static const string context("setting tags"); @@ -626,6 +629,10 @@ void setTagInfo(const SetTagInfoArgs &args) fileInfo.gatherRelatedNotifications(notifications); finalizeLog(); cout << " - Changes have been applied." << endl; + } catch(const Media::OperationAbortedException &) { + finalizeLog(); + cerr << Phrases::Warning << "The operation has been aborted." << endl; + return; } catch(const Media::Failure &) { finalizeLog(); cerr << " - " << Phrases::Error << "Failed to apply changes." << endl;