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:
parent
7f7d5f22c7
commit
358b105b1b
|
@ -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;
|
||||
|
|
13
cli/helper.h
13
cli/helper.h
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue