From f61e50cbd511504135a5663fec8029a6d4aa2fbb Mon Sep 17 00:00:00 2001 From: Thulinma Date: Mon, 13 Nov 2017 15:21:51 +0100 Subject: [PATCH] Added support for default responses in triggers, added maximum execution time for triggers --- lib/triggers.cpp | 36 +++++++++++++++++++++------ lib/triggers.h | 2 +- src/controller/controller_storage.cpp | 6 +++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/lib/triggers.cpp b/lib/triggers.cpp index d9e82ccf..fc6d5100 100644 --- a/lib/triggers.cpp +++ b/lib/triggers.cpp @@ -30,7 +30,7 @@ namespace Triggers{ ///\param payload This data will be sent to the destionation URL/program ///\param sync If true, handler is executed blocking and uses the response data. ///\returns String, false if further processing should be aborted. - std::string handleTrigger(const std::string &trigger, const std::string &value, const std::string &payload, int sync){ + std::string handleTrigger(const std::string &trigger, const std::string &value, const std::string &payload, int sync, const std::string &defaultResponse){ if (!value.size()){ WARN_MSG("Trigger requested with empty destination"); return "true"; @@ -44,8 +44,8 @@ namespace Triggers{ if (DL.post(url, payload, sync) && sync && DL.isOk()){ return DL.data(); } - /// \TODO Send default response. - return "true"; + FAIL_MSG("Trigger failed to execute (%s), using default response: %s", DL.getStatusText().c_str(), defaultResponse.c_str()); + return defaultResponse; }else{// send payload to stdin of newly forked process int fdIn = -1; int fdOut = -1; @@ -58,14 +58,28 @@ namespace Triggers{ pid_t myProc = Util::Procs::StartPiped(argv, &fdIn, &fdOut, &fdErr); // start new process and return stdin file desc. if (fdIn == -1 || fdOut == -1 || fdErr == -1){// verify fdIn FAIL_MSG("StartPiped returned invalid fd"); - return "true"; /// \todo Return true/false based on config here. + return defaultResponse; } write(fdIn, payload.data(), payload.size()); shutdown(fdIn, SHUT_RDWR); close(fdIn); if (sync){// if sync!=0 wait for response - while (Util::Procs::isActive(myProc)){Util::sleep(100);} + uint32_t counter = 0; + while (Util::Procs::isActive(myProc) && counter < 150){ + Util::sleep(100); + ++counter; + if (counter >= 150){ + if (counter == 150){ + FAIL_MSG("Trigger taking too long - killing process"); + } + if (counter >= 250){ + Util::Procs::Stop(myProc); + }else{ + Util::Procs::Murder(myProc); + } + } + } std::string ret; FILE *outFile = fdopen(fdOut, "r"); char *fileBuf = 0; @@ -75,11 +89,15 @@ namespace Triggers{ free(fileBuf); close(fdOut); close(fdErr); + if (counter >= 150){ + WARN_MSG("Using default trigger response: %s", defaultResponse.c_str()); + return defaultResponse; + } return ret; } close(fdOut); close(fdErr); - return "true"; + return defaultResponse; } } @@ -166,15 +184,17 @@ namespace Triggers{ if (isHandled && paramsCB){ isHandled = paramsCB(trigs.getPointer("params", i), extraParam); } + std::string defaultResponse = trigs.getPointer("default", i); + if (!defaultResponse.size()){defaultResponse = "true";} if (isHandled){ INFO_MSG("%s trigger handled by %s", type.c_str(), uri.c_str()); if (dryRun){return true;} if (sync){ - response = handleTrigger(type, uri, payload, sync); // do it. + response = handleTrigger(type, uri, payload, sync, defaultResponse); // do it. retVal &= Util::stringToBool(response); }else{ - std::string unused_response = handleTrigger(type, uri, payload, sync); // do it. + std::string unused_response = handleTrigger(type, uri, payload, sync, defaultResponse); // do it. retVal &= Util::stringToBool(unused_response); } } diff --git a/lib/triggers.h b/lib/triggers.h index d6de8204..e69c349f 100644 --- a/lib/triggers.h +++ b/lib/triggers.h @@ -6,7 +6,7 @@ namespace Triggers{ static const std::string empty; bool doTrigger(const std::string & triggerType, const std::string &payload, const std::string &streamName, bool dryRun, std::string &response, bool paramsCB(const char *, const void *) = 0, const void * extraParam = 0); - std::string handleTrigger(const std::string &triggerType, const std::string &value, const std::string &payload, int sync); + std::string handleTrigger(const std::string &triggerType, const std::string &value, const std::string &payload, int sync, const std::string &defaultResponse); // All of the below are just shorthands for specific usage of the doTrigger function above: bool shouldTrigger(const std::string & triggerType, const std::string &streamName = empty, bool paramsCB(const char *, const void *) = 0, const void * extraParam = 0); diff --git a/src/controller/controller_storage.cpp b/src/controller/controller_storage.cpp index d0f2d4b0..59cca307 100644 --- a/src/controller/controller_storage.cpp +++ b/src/controller/controller_storage.cpp @@ -170,6 +170,7 @@ namespace Controller{ tPage.addField("sync", RAX_UINT); tPage.addField("streams", RAX_256RAW); tPage.addField("params", RAX_128STRING); + tPage.addField("default", RAX_128STRING); tPage.setReady(); uint32_t i = 0; uint32_t max = (32 * 1024 - tPage.getOffset()) / tPage.getRSize(); @@ -221,6 +222,11 @@ namespace Controller{ }else{ tPage.setString("params", "", i); } + if (triggIt->isMember("default") && !(*triggIt)["default"].isNull()){ + tPage.setString("default", (*triggIt)["default"].asStringRef(), i); + }else{ + tPage.setString("default", "", i); + } } ++i;