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.
This commit is contained in:
Martchus 2017-10-09 19:06:26 +02:00
parent 7f7d5f22c7
commit 358b105b1b
3 changed files with 60 additions and 0 deletions

View File

@ -12,6 +12,7 @@
#include <iostream>
#include <cstring>
#include <csignal>
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<void()> InterruptHandler::s_handler;
bool InterruptHandler::s_handlerRegistered = false;
InterruptHandler::InterruptHandler(std::function<void ()> 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()>();
}
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;

View File

@ -158,6 +158,19 @@ inline FieldValue::FieldValue(DenotationType type, unsigned int fileIndex, const
value(value)
{}
class InterruptHandler
{
public:
InterruptHandler(std::function<void()> handler);
~InterruptHandler();
private:
static void handler(int signum);
static std::function<void()> s_handler;
static bool s_handlerRegistered;
};
}
// define hash functions for custom data types

View File

@ -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;