Daemon intended to replace a Cronjob which reads and processes events from a queue

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.



At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.



#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <map>
#include <regex>
// daemon functions
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
// logs
#include <fstream>
#include <chrono>
#include <ctime>
#include <iomanip>

void logOutput(std::string);

static void daemon();

std::string exec(const char* cmd);

enum EventAction eventActioned,
eventOne,
eventTwo ;

static std::map<std::string, EventAction> mapValueToEvent;

void initialise();

int main()
syslog(LOG_ERR, "bendaemon has started");
daemon();
initialise();

for(int i = 0; i < 20; ++i)
std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
switch(mapValueToEvent[result])
case eventOne:
// process event one
logOutput("one");
break;
case eventTwo:
// process event two
break;
case eventActioned:
// write some event complete log
logOutput("zero");
sleep(20);
break;
default:
// event not defined. write some error log
break;



syslog(LOG_ERR, "Terminating daemon");
closelog();
return EXIT_SUCCESS;


std::string exec(const char* cmd)
std::array<char, 4096> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get()))
if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
result += buffer.data();


std::regex expression("EXITCODE-0");
if(std::regex_search(result, expression) == 1)
result = "1";

else
result = "0";

return result;


void initialise()
mapValueToEvent["1"] = eventOne;
mapValueToEvent["2"] = eventTwo;
mapValueToEvent["0"] = eventActioned;


void logOutput(std::string value)
std::ofstream logFile;
logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
return;


static void daemon()
pid_t pid;
// Fork off the parent process
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);

// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);

// On success: The child process becomes session leader
if (setsid() < 0)
exit(EXIT_FAILURE);

//TODO: Implement a working signal handler
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
// Fork off for the second time (detatch from terminal window)
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);

// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);

umask(0);
// This may need to point to a different directory in the future
chdir("/");
// Close all open file descriptors
for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
close (x);

// Open the log file
openlog("bendaemon", LOG_PID, LOG_DAEMON);







share|improve this question



























    up vote
    3
    down vote

    favorite












    The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.



    At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.



    #include <cstdio>
    #include <iostream>
    #include <memory>
    #include <stdexcept>
    #include <string>
    #include <array>
    #include <map>
    #include <regex>
    // daemon functions
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <syslog.h>
    // logs
    #include <fstream>
    #include <chrono>
    #include <ctime>
    #include <iomanip>

    void logOutput(std::string);

    static void daemon();

    std::string exec(const char* cmd);

    enum EventAction eventActioned,
    eventOne,
    eventTwo ;

    static std::map<std::string, EventAction> mapValueToEvent;

    void initialise();

    int main()
    syslog(LOG_ERR, "bendaemon has started");
    daemon();
    initialise();

    for(int i = 0; i < 20; ++i)
    std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
    switch(mapValueToEvent[result])
    case eventOne:
    // process event one
    logOutput("one");
    break;
    case eventTwo:
    // process event two
    break;
    case eventActioned:
    // write some event complete log
    logOutput("zero");
    sleep(20);
    break;
    default:
    // event not defined. write some error log
    break;



    syslog(LOG_ERR, "Terminating daemon");
    closelog();
    return EXIT_SUCCESS;


    std::string exec(const char* cmd)
    std::array<char, 4096> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get()))
    if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
    result += buffer.data();


    std::regex expression("EXITCODE-0");
    if(std::regex_search(result, expression) == 1)
    result = "1";

    else
    result = "0";

    return result;


    void initialise()
    mapValueToEvent["1"] = eventOne;
    mapValueToEvent["2"] = eventTwo;
    mapValueToEvent["0"] = eventActioned;


    void logOutput(std::string value)
    std::ofstream logFile;
    logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
    std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
    return;


    static void daemon()
    pid_t pid;
    // Fork off the parent process
    pid = fork();
    // An error occurred
    if (pid < 0)
    exit(EXIT_FAILURE);

    // Success: Let the parent terminate
    if (pid > 0)
    exit(EXIT_SUCCESS);

    // On success: The child process becomes session leader
    if (setsid() < 0)
    exit(EXIT_FAILURE);

    //TODO: Implement a working signal handler
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    // Fork off for the second time (detatch from terminal window)
    pid = fork();
    // An error occurred
    if (pid < 0)
    exit(EXIT_FAILURE);

    // Success: Let the parent terminate
    if (pid > 0)
    exit(EXIT_SUCCESS);

    umask(0);
    // This may need to point to a different directory in the future
    chdir("/");
    // Close all open file descriptors
    for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
    close (x);

    // Open the log file
    openlog("bendaemon", LOG_PID, LOG_DAEMON);







    share|improve this question























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.



      At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.



      #include <cstdio>
      #include <iostream>
      #include <memory>
      #include <stdexcept>
      #include <string>
      #include <array>
      #include <map>
      #include <regex>
      // daemon functions
      #include <stdlib.h>
      #include <unistd.h>
      #include <signal.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <syslog.h>
      // logs
      #include <fstream>
      #include <chrono>
      #include <ctime>
      #include <iomanip>

      void logOutput(std::string);

      static void daemon();

      std::string exec(const char* cmd);

      enum EventAction eventActioned,
      eventOne,
      eventTwo ;

      static std::map<std::string, EventAction> mapValueToEvent;

      void initialise();

      int main()
      syslog(LOG_ERR, "bendaemon has started");
      daemon();
      initialise();

      for(int i = 0; i < 20; ++i)
      std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
      switch(mapValueToEvent[result])
      case eventOne:
      // process event one
      logOutput("one");
      break;
      case eventTwo:
      // process event two
      break;
      case eventActioned:
      // write some event complete log
      logOutput("zero");
      sleep(20);
      break;
      default:
      // event not defined. write some error log
      break;



      syslog(LOG_ERR, "Terminating daemon");
      closelog();
      return EXIT_SUCCESS;


      std::string exec(const char* cmd)
      std::array<char, 4096> buffer;
      std::string result;
      std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
      if (!pipe) throw std::runtime_error("popen() failed!");
      while (!feof(pipe.get()))
      if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
      result += buffer.data();


      std::regex expression("EXITCODE-0");
      if(std::regex_search(result, expression) == 1)
      result = "1";

      else
      result = "0";

      return result;


      void initialise()
      mapValueToEvent["1"] = eventOne;
      mapValueToEvent["2"] = eventTwo;
      mapValueToEvent["0"] = eventActioned;


      void logOutput(std::string value)
      std::ofstream logFile;
      logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
      std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
      logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
      return;


      static void daemon()
      pid_t pid;
      // Fork off the parent process
      pid = fork();
      // An error occurred
      if (pid < 0)
      exit(EXIT_FAILURE);

      // Success: Let the parent terminate
      if (pid > 0)
      exit(EXIT_SUCCESS);

      // On success: The child process becomes session leader
      if (setsid() < 0)
      exit(EXIT_FAILURE);

      //TODO: Implement a working signal handler
      signal(SIGCHLD, SIG_IGN);
      signal(SIGHUP, SIG_IGN);
      // Fork off for the second time (detatch from terminal window)
      pid = fork();
      // An error occurred
      if (pid < 0)
      exit(EXIT_FAILURE);

      // Success: Let the parent terminate
      if (pid > 0)
      exit(EXIT_SUCCESS);

      umask(0);
      // This may need to point to a different directory in the future
      chdir("/");
      // Close all open file descriptors
      for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
      close (x);

      // Open the log file
      openlog("bendaemon", LOG_PID, LOG_DAEMON);







      share|improve this question













      The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.



      At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.



      #include <cstdio>
      #include <iostream>
      #include <memory>
      #include <stdexcept>
      #include <string>
      #include <array>
      #include <map>
      #include <regex>
      // daemon functions
      #include <stdlib.h>
      #include <unistd.h>
      #include <signal.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <syslog.h>
      // logs
      #include <fstream>
      #include <chrono>
      #include <ctime>
      #include <iomanip>

      void logOutput(std::string);

      static void daemon();

      std::string exec(const char* cmd);

      enum EventAction eventActioned,
      eventOne,
      eventTwo ;

      static std::map<std::string, EventAction> mapValueToEvent;

      void initialise();

      int main()
      syslog(LOG_ERR, "bendaemon has started");
      daemon();
      initialise();

      for(int i = 0; i < 20; ++i)
      std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
      switch(mapValueToEvent[result])
      case eventOne:
      // process event one
      logOutput("one");
      break;
      case eventTwo:
      // process event two
      break;
      case eventActioned:
      // write some event complete log
      logOutput("zero");
      sleep(20);
      break;
      default:
      // event not defined. write some error log
      break;



      syslog(LOG_ERR, "Terminating daemon");
      closelog();
      return EXIT_SUCCESS;


      std::string exec(const char* cmd)
      std::array<char, 4096> buffer;
      std::string result;
      std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
      if (!pipe) throw std::runtime_error("popen() failed!");
      while (!feof(pipe.get()))
      if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
      result += buffer.data();


      std::regex expression("EXITCODE-0");
      if(std::regex_search(result, expression) == 1)
      result = "1";

      else
      result = "0";

      return result;


      void initialise()
      mapValueToEvent["1"] = eventOne;
      mapValueToEvent["2"] = eventTwo;
      mapValueToEvent["0"] = eventActioned;


      void logOutput(std::string value)
      std::ofstream logFile;
      logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
      std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
      logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
      return;


      static void daemon()
      pid_t pid;
      // Fork off the parent process
      pid = fork();
      // An error occurred
      if (pid < 0)
      exit(EXIT_FAILURE);

      // Success: Let the parent terminate
      if (pid > 0)
      exit(EXIT_SUCCESS);

      // On success: The child process becomes session leader
      if (setsid() < 0)
      exit(EXIT_FAILURE);

      //TODO: Implement a working signal handler
      signal(SIGCHLD, SIG_IGN);
      signal(SIGHUP, SIG_IGN);
      // Fork off for the second time (detatch from terminal window)
      pid = fork();
      // An error occurred
      if (pid < 0)
      exit(EXIT_FAILURE);

      // Success: Let the parent terminate
      if (pid > 0)
      exit(EXIT_SUCCESS);

      umask(0);
      // This may need to point to a different directory in the future
      chdir("/");
      // Close all open file descriptors
      for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
      close (x);

      // Open the log file
      openlog("bendaemon", LOG_PID, LOG_DAEMON);









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 4 at 3:07









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Jan 4 at 2:58









      pcgben

      1383




      1383




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          I'm not going to comment on the OS interactions here, just the C++ code in general.



          prefer anonymous namespaces to the static keyword



          static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:



          namespace 
          void daemon();
          std::map<std::string, EventAction> mapValueToEvent;



          Prefer using enum class to regular enum



          enum class EventAction ...;


          This prevents a large number of namespace polution issues, and is just a good habit to build.



          prefer using std::unordered_map to std::map



          Unless you have a reallllly good reason, std::unordered_map is almost always preferable.



          Why shared_ptr?



          std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);


          While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.



          initialise() is unnecessary



          You can simply initialize the map using a literal:



          static std::map<std::string, EventAction> mapValueToEvent = 
          "1", eventOne,
          "2", eventTwo,
          "0", eventActioned
          ;


          Logic error, exec() can only return "0" or "1"



          That doesn't feel right, since you handle "0", "1" or "2"






          share|improve this answer





















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184244%2fdaemon-intended-to-replace-a-cronjob-which-reads-and-processes-events-from-a-que%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            2
            down vote



            accepted










            I'm not going to comment on the OS interactions here, just the C++ code in general.



            prefer anonymous namespaces to the static keyword



            static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:



            namespace 
            void daemon();
            std::map<std::string, EventAction> mapValueToEvent;



            Prefer using enum class to regular enum



            enum class EventAction ...;


            This prevents a large number of namespace polution issues, and is just a good habit to build.



            prefer using std::unordered_map to std::map



            Unless you have a reallllly good reason, std::unordered_map is almost always preferable.



            Why shared_ptr?



            std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);


            While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.



            initialise() is unnecessary



            You can simply initialize the map using a literal:



            static std::map<std::string, EventAction> mapValueToEvent = 
            "1", eventOne,
            "2", eventTwo,
            "0", eventActioned
            ;


            Logic error, exec() can only return "0" or "1"



            That doesn't feel right, since you handle "0", "1" or "2"






            share|improve this answer

























              up vote
              2
              down vote



              accepted










              I'm not going to comment on the OS interactions here, just the C++ code in general.



              prefer anonymous namespaces to the static keyword



              static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:



              namespace 
              void daemon();
              std::map<std::string, EventAction> mapValueToEvent;



              Prefer using enum class to regular enum



              enum class EventAction ...;


              This prevents a large number of namespace polution issues, and is just a good habit to build.



              prefer using std::unordered_map to std::map



              Unless you have a reallllly good reason, std::unordered_map is almost always preferable.



              Why shared_ptr?



              std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);


              While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.



              initialise() is unnecessary



              You can simply initialize the map using a literal:



              static std::map<std::string, EventAction> mapValueToEvent = 
              "1", eventOne,
              "2", eventTwo,
              "0", eventActioned
              ;


              Logic error, exec() can only return "0" or "1"



              That doesn't feel right, since you handle "0", "1" or "2"






              share|improve this answer























                up vote
                2
                down vote



                accepted







                up vote
                2
                down vote



                accepted






                I'm not going to comment on the OS interactions here, just the C++ code in general.



                prefer anonymous namespaces to the static keyword



                static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:



                namespace 
                void daemon();
                std::map<std::string, EventAction> mapValueToEvent;



                Prefer using enum class to regular enum



                enum class EventAction ...;


                This prevents a large number of namespace polution issues, and is just a good habit to build.



                prefer using std::unordered_map to std::map



                Unless you have a reallllly good reason, std::unordered_map is almost always preferable.



                Why shared_ptr?



                std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);


                While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.



                initialise() is unnecessary



                You can simply initialize the map using a literal:



                static std::map<std::string, EventAction> mapValueToEvent = 
                "1", eventOne,
                "2", eventTwo,
                "0", eventActioned
                ;


                Logic error, exec() can only return "0" or "1"



                That doesn't feel right, since you handle "0", "1" or "2"






                share|improve this answer













                I'm not going to comment on the OS interactions here, just the C++ code in general.



                prefer anonymous namespaces to the static keyword



                static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:



                namespace 
                void daemon();
                std::map<std::string, EventAction> mapValueToEvent;



                Prefer using enum class to regular enum



                enum class EventAction ...;


                This prevents a large number of namespace polution issues, and is just a good habit to build.



                prefer using std::unordered_map to std::map



                Unless you have a reallllly good reason, std::unordered_map is almost always preferable.



                Why shared_ptr?



                std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);


                While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.



                initialise() is unnecessary



                You can simply initialize the map using a literal:



                static std::map<std::string, EventAction> mapValueToEvent = 
                "1", eventOne,
                "2", eventTwo,
                "0", eventActioned
                ;


                Logic error, exec() can only return "0" or "1"



                That doesn't feel right, since you handle "0", "1" or "2"







                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered Jan 4 at 3:20









                Frank

                2,947319




                2,947319






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184244%2fdaemon-intended-to-replace-a-cronjob-which-reads-and-processes-events-from-a-que%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation